zoukankan      html  css  js  c++  java
  • 原始战争之主界面滑动效果

    简介:在弄一个横版的游戏,需要一个随鼠标左右滑动的功能,最终做了一个拖动的效果。

    • 鼠标左右移动界面也滑动
      • 实际做的时候,搜了一下没有滑动的方案,那就假想游戏界面长度大于窗口界面(类比给卷轴加游标),然后根据鼠标左右移动事件,去计算卷轴应该在的位置,然后更新界面。如果左右移动处理麻烦(滚动速度太快或太慢,现在如果玩红警95就存在鼠标移动速度问题),也可以在血条中间加上一个滑动条,来精确的控制位置。

    打算用图片来模拟卷轴大小

    来用一个光头的图片来模拟的时候,发现一个问题:

    QLabel设置大小无效问题

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QFrame
    from PyQt5.QtCore import QSize
    from PyQt5.QtGui import QPixmap
    
    class War(QMainWindow):
        '''游戏主类'''
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            self.board = Scroll(self)
            
            # 窗口设置
            self.setFixedSize(QSize(720,480))
            self.setWindowTitle("原始战争")
            self.show()
    
    
    class Scroll(QFrame):
        '''卷轴测试类'''
        def __init__(self, parent):
            super().__init__(parent)
    
            self.lbl = QLabel(self)
            self.qpix=QPixmap(sys.path[0]+'/resource/57001_one_punch_man.jpg')
            self.lbl.setGeometry(0,0,720,480)
            self.lbl.setPixmap(self.qpix)
            
    if __name__ == '__main__':
        app = QApplication([])
        war = War()
        sys.exit(app.exec_())
    
    

    看效果

    发现图片没有显示出来,只显示在了左上角,其实不是QPixmap的问题,时QLabel大小设置的问题。如果把

    self.lbl = QLabel(self)
    self.qpix=QPixmap(sys.path[0]+'/resource/57001_one_punch_man.jpg')
    self.lbl.setGeometry(0,0,720,480)
    self.lbl.setPixmap(self.qpix)
    

    这段代码放到War类的initUI()方法下直接调用的话,是可以的,所以问题出在了其他类中的QLable下,初始化QLabel时我用的是self,试着用了下parent就好了。
    self.lbl = QLabel(parent)

    原因是
    QLabel::QLabel(QWidget *parent = nullptr, Qt::WindowFlags f = ...)
    第一个参数为父级QWidget对象。 Qt Documentation - QLabel Class

    这个问题是个小插曲,继续做滑动效果,为了方便测试还是在一个类做尝试。

    尝试用鼠标移动触发

    首先选择了好久最后打算用QScrollArea来处理

    先将滚动条加上

    def initUI(self):
    
            self.lbl = QLabel(self)
            self.qpix=QPixmap(sys.path[0]+'/resource/57001_one_punch_man.jpg').scaledToHeight(480)
            self.lbl.setGeometry(self.qpix.rect())
            self.lbl.setPixmap(self.qpix)
            
            # 添加滚动条,并添加组件
            scrollArea = QScrollArea(self)
            scrollArea.setWidget(self.lbl)
            scrollArea.resize(QSize(720,480))
     
            # 窗口设置
            self.resize(QSize(720,480))
            self.setWindowTitle("原始战争")
    

    self.qpix=QPixmap(sys.path[0]+'/resource/57001_one_punch_man.jpg').scaledToHeight(480)
    先把图定高等比例缩放。再添加滚动条。

    效果:

    搞定,鼠标拖动

    鼠标拖动也刚好解决了滑动烦人的速度问题,此处功能以后还可以做RTS用。

    在一个论坛看到一篇07年用C++写的拖动例子,关键在于重载滚动条的事件过滤

    bool eventFilter(QObject *o, QEvent *e)
    {
        if(o!=l)
            return QScrollArea::eventFilter(o,e);
        if(e->type()==QEvent::MouseButtonPress)
        {
            m_prev = ((QMouseEvent*)e)->pos();
            this->prev_diff.setX(0);
            this->prev_diff.setY(0);
            return true;
        }
        if(e->type()==QEvent::MouseMove)
        {
            QPoint pt = ((QMouseEvent*)e)->pos();
            this->diff = pt-m_prev-prev_diff*n;
            m_prev = pt;
            horizontalScrollBar()->setValue(horizontalScrollBar()->value()+diff.x()*n);
            verticalScrollBar()->setValue(verticalScrollBar()->value()+diff.y()*n);
            qDebug()<<"("+QString::number(diff.x())+","+QString::number(diff.y())+")";
            this->prev_diff=diff;
            return true;
        }
        return QScrollArea::eventFilter(o,e);
    }
    
    

    改了一下:

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QFrame, QScrollArea, QWidget, QVBoxLayout, QHBoxLayout, 
    QScrollBar, QAbstractScrollArea
    from PyQt5.QtCore import QSize, Qt, QEvent, QPoint
    from PyQt5.QtGui import QPixmap
    
    class War(QMainWindow):
        '''游戏主类'''
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
    
            self.lbl = QLabel(self)
            self.qpix=QPixmap(sys.path[0]+'/resource/57001_one_punch_man.jpg').scaledToHeight(480)
            self.lbl.setGeometry(self.qpix.rect())
            self.lbl.setPixmap(self.qpix)
            print(self.lbl)
            # 添加滚动条,并添加组件
            scrollArea = ScrollArea(self)
            scrollArea.setWidgetResizable(True)
            #scrollArea.setBackgroundRole(QPalette::Dark);
            scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 隐藏滚动条
            scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            scrollArea.setWidget(self.lbl)
            scrollArea.resize(QSize(720,480))
      
            # 窗口设置
            self.resize(QSize(720,480))
            self.setWindowTitle("原始战争")
    
            #self.scroll(400,200)
            #self.update()
    
    class ScrollArea(QScrollArea):
        '''重载滚动条类'''
        def __init__(self, parent):
            super().__init__(parent)
    
            self.n=0.8
            self.m_prev = QPoint()
            self.diff = QPoint()
            self.prev_diff = QPoint(0, 0)
            self.widget = None
    
    
        def setWidget(self, w):
            '''设置区域部件时,对象赋值'''
            super().setWidget(w)
            self.widget=w
            self.widget.installEventFilter(self)
            
        def eventFilter(self,obj,evt):
            '''事件过滤'''
            #print(QScrollArea.widget(self),obj)
            if(obj!=self.widget):
                return super().eventFilter(obj,evt)
            
            if(evt.type()==QEvent.MouseButtonPress):
                self.m_prev = evt.pos()
                self.prev_diff.setX(0)
                self.prev_diff.setY(0)
    
            # 鼠标移动
            # MouseMove为鼠标拖动效果,鼠标滑动是ToolTip
            if(evt.type()==QEvent.MouseMove):  
                #print(evt.pos())
                pt = evt.pos()
                self.diff = pt-self.m_prev-self.prev_diff*self.n
                self.diff = -1*self.diff
                print('diff x :',self.diff.x())
                self.m_prev = pt
                
                print(self.horizontalScrollBar().value()+self.diff.x()*self.n,'--')
                self.horizontalScrollBar().setValue(self.horizontalScrollBar().value()+self.diff.x()*self.n)
                # horizontalScrollBar().setValue(horizontalScrollBar().value()+self.diff.x()*self.n);
                # verticalScrollBar()->setValue(verticalScrollBar()->value()+diff.y()*n); # 竖向暂时不需要移动
                self.prev_diff=self.diff;
                return True
            return QScrollArea.eventFilter(self,obj, evt)
    
       
    if __name__ == '__main__':
        app = QApplication([])
        war = War()
        war.show()
        sys.exit(app.exec_())
    

    github

    最终界面效果:

    总结

    QT做的太好了,看C++文档和代码,一般理解了都可以无缝用PY重写。
    以为俩小时能搞好的,搞了一天。英语还是很重要,就是没动力学 嗝。

    最佳实践就是动手去做,在实战中学习、成长,而不是等所有的都准备好之后再开始。这两天园子首页的推荐彼之蜜糖,吾之砒霜——聊聊软件开发中的最佳实践

    参考,致谢

  • 相关阅读:
    设置tomcat访问根路径
    关于Java抽象类的理解
    JavaIO
    synchronized关键字
    Java线程池
    Codeforces1478F-Nezzar and Nice Beatmap
    Codeforces1477B-Nezzar and Binary String
    Codeforces1476D Journey
    Codeforces1478D Nezzar and Board
    Codeforces Round #697 (Div. 3)G. Strange Beauty
  • 原文地址:https://www.cnblogs.com/warcraft/p/9464100.html
Copyright © 2011-2022 走看看