Stubborn 发表于 2021-11-25 23:40:33

关于QT5的:副窗口QWidget和QPainter的层次问题








如图所示,我的QPainter没有工作在副QWidget窗口,工作在主窗口上面,导致被遮挡,请问应该如何解决这个问题,让QPainter工作与顶部不被遮挡,一下是我的代码demo


# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.Do not edit this file unless you know what you are doing.


from PyQt5.QtGui import QPainter, QPen, QColor, QRadialGradient, QBrush
from PyQt5.QtCore import Qt, QPoint
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
      MainWindow.setObjectName("MainWindow")
      MainWindow.resize(800, 600)
      self.centralwidget = QtWidgets.QWidget(MainWindow)
      self.centralwidget.setObjectName("centralwidget")
      self.widget = QtWidgets.QWidget(self.centralwidget)
      self.widget.setGeometry(QtCore.QRect(250, 70, 301, 261))
      self.widget.setObjectName("widget")
      self.widget.setStyleSheet("background-color:green;")
      MainWindow.setCentralWidget(self.centralwidget)
      self.menubar = QtWidgets.QMenuBar(MainWindow)
      self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
      self.menubar.setObjectName("menubar")
      MainWindow.setMenuBar(self.menubar)
      self.statusbar = QtWidgets.QStatusBar(MainWindow)
      self.statusbar.setObjectName("statusbar")
      MainWindow.setStatusBar(self.statusbar)

      self.retranslateUi(MainWindow)
      QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
      _translate = QtCore.QCoreApplication.translate
      MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))

class Gomoku(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self, parent=None, *args, **kwargs):
      super().__init__(parent, *args, **kwargs)
      self.setupUi(self)
      #self.paintEvent = self.widget.paintEvent

    def paintEvent(self, e):
      def draw_map():
            """绘制棋盘"""
            qp.setPen(QPen(QColor(0, 0, 0), 2, Qt.SolidLine))# 棋盘的颜色为黑色
            # 绘制横线
            for x in range(15):
                qp.drawLine(40 * (x + 1), 40, 40 * (x + 1), 600)
            # 绘制竖线
            for y in range(15):
                qp.drawLine(40, 40 * (y + 1), 600, 40 * (y + 1))
            # 绘制棋盘中的黑点
            qp.setBrush(QColor(0, 0, 0))
            key_points = [(4, 4), (12, 4), (4, 12), (12, 12), (8, 8)]
            for t in key_points:
                qp.drawEllipse(QPoint(40 * t, 40 * t), 5, 5)

      qp = QPainter()
      qp.begin(self)
      draw_map()# 绘制棋盘


if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)

    game = Gomoku()

    game.show()

    sys.exit(app.exec_())

lightninng 发表于 2021-11-26 02:14:37

因为已经放弃PyQt5,转用PySide2了,所以没办法测试代码,盲猜一下吧
根据这个文档https://blog.csdn.net/jia666666/article/details/81566599
方法                描述
begin()        开始在目标设备上绘制
begin方法要传入一个参数,这个参数就是painter对象工作的控件,所以如果你是想在图中绿色的方块上绘制图像,试试把qp.begin(self)改为qp.begin(self.widget)

但是,从你的描述上,个人理解,你并不是想把棋盘绘制在绿色块上,只是想绘制的棋盘黑线要在绿色方块上方而不是被绿色方块覆盖。如果是这样,看看这篇
https://blog.csdn.net/qq_27061049/article/details/109391064
个人未尝试,因为PyQt5和PySide2同时装的时候用pyinstaller打包时会有莫名其妙的找不到依赖库的错误,所以,我现在基本上已经完全放弃装PyQt5库了
希望以上回答~~对你有所帮助~~

Stubborn 发表于 2021-11-26 07:56:01

lightninng 发表于 2021-11-26 02:14
因为已经放弃PyQt5,转用PySide2了,所以没办法测试代码,盲猜一下吧
根据这个文档https://blog.csdn.net/ ...

不管是在绿色工作区绘制,还是修改层都已经尝试过了,非常感谢,有其他的方法吗?
self.widget.lower()
self.widget.stackUnder(self.centralwidget)

qp.begin(self.widget)
#这个似乎不会触发事件,尝试过在子类重载,也不行
#self.paintEvent = self.widget.paintEvent

hrpzcf 发表于 2021-11-26 09:27:52

写一个类PWidget,继承QWidget,在里面实现paintEvent,Gomoku里使用该PWidget控件,删除Ui_MainWindow里的QWidget。

hrpzcf 发表于 2021-11-26 12:12:13

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.Do not edit this file unless you know what you are doing.


from PyQt5.QtGui import QPainter, QPen, QColor, QRadialGradient, QBrush
from PyQt5.QtCore import Qt, QPoint
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
      MainWindow.setObjectName("MainWindow")
      MainWindow.resize(800, 600)
      self.centralwidget = QtWidgets.QWidget(MainWindow)
      self.centralwidget.setObjectName("centralwidget")

      MainWindow.setCentralWidget(self.centralwidget)
      self.menubar = QtWidgets.QMenuBar(MainWindow)
      self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
      self.menubar.setObjectName("menubar")
      MainWindow.setMenuBar(self.menubar)
      self.statusbar = QtWidgets.QStatusBar(MainWindow)
      self.statusbar.setObjectName("statusbar")
      MainWindow.setStatusBar(self.statusbar)

      self.retranslateUi(MainWindow)
      QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
      _translate = QtCore.QCoreApplication.translate
      MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))


class PWidget(QtWidgets.QWidget):
    def __init__(self, parent=None, *args, **kwargs):
      super().__init__(parent, *args, **kwargs)

    def paintEvent(self, e):
      def draw_map():
            """绘制棋盘"""
            qp.drawRect(self.rect())
            qp.setBackground(QColor("green"))
            qp.setPen(QPen(QColor(0, 0, 0), 2, Qt.SolidLine))# 棋盘的颜色为黑色
            # 绘制横线
            for x in range(15):
                qp.drawLine(40 * (x + 1), 40, 40 * (x + 1), 600)
            # 绘制竖线
            for y in range(15):
                qp.drawLine(40, 40 * (y + 1), 600, 40 * (y + 1))
            # 绘制棋盘中的黑点
            qp.setBrush(QColor(0, 0, 0))
            key_points = [(4, 4), (12, 4), (4, 12), (12, 12), (8, 8)]
            for t in key_points:
                qp.drawEllipse(QPoint(40 * t, 40 * t), 5, 5)

      qp = QPainter()
      qp.begin(self)
      qp.fillRect(self.rect(), QColor("green"))# 用此绘制背景
      draw_map()# 绘制棋盘


class Gomoku(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None, *args, **kwargs):
      super().__init__(parent, *args, **kwargs)
      self.setupUi(self)
      # self.paintEvent = self.widget.paintEvent
      self.setwidget()# 调用

    def setwidget(self):
      # 具体的绘制区域有待优化
      # 最好self.centralwidget添加一个布局,此布局添加self.widget
      self.widget = PWidget(self.centralwidget)
      self.widget.setGeometry(QtCore.QRect(250, 70, 301, 261))
      # self.widget.setStyleSheet("background-color:green;")


if __name__ == "__main__":
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)

    game = Gomoku()

    game.show()

    sys.exit(app.exec_())

Stubborn 发表于 2021-11-26 12:50:45

本帖最后由 Stubborn 于 2021-11-26 12:55 编辑

hrpzcf 发表于 2021-11-26 09:27
写一个类PWidget,继承QWidget,在里面实现paintEvent,Gomoku里使用该PWidget控件,删除Ui_MainWindow里的 ...

平常都不接触qt5,想写一个界面的人机五子棋对战,非常感谢大佬的帮助,,对知识并不熟{:5_95:}

另外还有一个小疑问,因为后期需要绘制“黑白棋子,”看代码情况,是不是应该在PWidget实现我的绘制棋子的功能

lightninng 发表于 2021-11-26 12:51:34

本帖最后由 lightninng 于 2021-11-26 12:55 编辑

hrpzcf 发表于 2021-11-26 12:12


赞一个~~

lightninng 发表于 2021-11-26 12:56:33

Stubborn 发表于 2021-11-26 12:50
平常都不接触qt5,想写一个界面的人机五子棋对战,非常感谢大佬的帮助,,对知识并不熟

另 ...

楼主,想问一下。那个绿色块是干嘛的,哈哈哈哈。好像和你的问题无关~~

hrpzcf 发表于 2021-11-26 13:22:59

本帖最后由 hrpzcf 于 2021-11-26 13:24 编辑

Stubborn 发表于 2021-11-26 12:50
平常都不接触qt5,想写一个界面的人机五子棋对战,非常感谢大佬的帮助,,对知识并不熟

另 ...

在PWidget里实现相关的函数,比如在PWidget写个在某坐标绘制棋子函数def dropChessman(self, t, x, y): ...,主窗口Gomoku里这么调用: self.widget.dropChessman("黑", 1, 2)。如果用到动作信号,主窗口某信号也可以这么连接这个函数(比如按钮xxx):btn_xxx.click.connect(lambda: self.widget.dropChessman("黑", 1, 2))

乍一看比较乱,也许大概应该就是这个样子了,好久不看QT5了,可能有写错的
PS: 也许PWidget里可以把QPainter实例qp保存成实例属性

hrpzcf 发表于 2021-11-26 13:26:15

lightninng 发表于 2021-11-26 12:56
楼主,想问一下。那个绿色块是干嘛的,哈哈哈哈。好像和你的问题无关~~

啊这个,主要是楼主画的背景,我也跟着画了,如果不画背景不好看出来棋盘已经画在widget上了{:10_250:}

Stubborn 发表于 2021-11-26 14:18:09

本帖最后由 Stubborn 于 2021-11-26 14:19 编辑

lightninng 发表于 2021-11-26 12:56
楼主,想问一下。那个绿色块是干嘛的,哈哈哈哈。好像和你的问题无关~~

五子棋棋盘呐,上面话格子的{:5_97:}


主窗口还有其他功能

lightninng 发表于 2021-11-26 16:52:27

Stubborn 发表于 2021-11-26 14:18
五子棋棋盘呐,上面话格子的




原来如此,是绿色板子上画棋盘~~
页: [1]
查看完整版本: 关于QT5的:副窗口QWidget和QPainter的层次问题