Python 如何在PyQt上绘制适当的网格? 让我们考虑一下这个小片段: import sys from PyQt5 import QtWidgets from PyQt5 import QtCore from PyQt5 import QtGui from PyQt5.QtWidgets import QMenu from PyQt5.QtGui import QKeySequence from PyQt5.QtCore import Qt from PyQt5.QtGui import QCursor def create_action(parent, text, slot=None, shortcut=None, shortcuts=None, shortcut_context=None, icon=None, tooltip=None, checkable=False, checked=False): action = QtWidgets.QAction(text, parent) if icon is not None: action.setIcon(QIcon(':/%s.png' % icon)) if shortcut is not None: action.setShortcut(shortcut) if shortcuts is not None: action.setShortcuts(shortcuts) if shortcut_context is not None: action.setShortcutContext(shortcut_context) if tooltip is not None: action.setToolTip(tooltip) action.setStatusTip(tooltip) if checkable: action.setCheckable(True) if checked: action.setChecked(True) if slot is not None: action.triggered.connect(slot) return action class Settings(): WIDTH = 20 HEIGHT = 15 NUM_BLOCKS_X = 10 NUM_BLOCKS_Y = 14 class QS(QtWidgets.QGraphicsScene): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) width = Settings.NUM_BLOCKS_X * Settings.WIDTH height = Settings.NUM_BLOCKS_Y * Settings.HEIGHT self.setSceneRect(0, 0, width, height) self.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex) class QV(QtWidgets.QGraphicsView): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.view_menu = QMenu(self) self.create_actions() def create_actions(self): act = create_action(self.view_menu, "Zoom in", slot=self.on_zoom_in, shortcut=QKeySequence("+"), shortcut_context=Qt.WidgetShortcut) self.view_menu.addAction(act) act = create_action(self.view_menu, "Zoom out", slot=self.on_zoom_out, shortcut=QKeySequence("-"), shortcut_context=Qt.WidgetShortcut) self.view_menu.addAction(act) self.addActions(self.view_menu.actions()) def on_zoom_in(self): if not self.scene(): return self.scale(1.5, 1.5) def on_zoom_out(self): if not self.scene(): return self.scale(1.0 / 1.5, 1.0 / 1.5) def drawBackground(self, painter, rect): gr = rect.toRect() start_x = gr.left() + Settings.WIDTH - (gr.left() % Settings.WIDTH) start_y = gr.top() + Settings.HEIGHT - (gr.top() % Settings.HEIGHT) painter.save() painter.setPen(QtGui.QColor(60, 70, 80).lighter(90)) painter.setOpacity(0.7) for x in range(start_x, gr.right(), Settings.WIDTH): painter.drawLine(x, gr.top(), x, gr.bottom()) for y in range(start_y, gr.bottom(), Settings.HEIGHT): painter.drawLine(gr.left(), y, gr.right(), y) painter.restore() super().drawBackground(painter, rect) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) a = QS() b = QV() b.setScene(a) # b.resize(800,600) b.show() sys.exit(app.exec_())

Python 如何在PyQt上绘制适当的网格? 让我们考虑一下这个小片段: import sys from PyQt5 import QtWidgets from PyQt5 import QtCore from PyQt5 import QtGui from PyQt5.QtWidgets import QMenu from PyQt5.QtGui import QKeySequence from PyQt5.QtCore import Qt from PyQt5.QtGui import QCursor def create_action(parent, text, slot=None, shortcut=None, shortcuts=None, shortcut_context=None, icon=None, tooltip=None, checkable=False, checked=False): action = QtWidgets.QAction(text, parent) if icon is not None: action.setIcon(QIcon(':/%s.png' % icon)) if shortcut is not None: action.setShortcut(shortcut) if shortcuts is not None: action.setShortcuts(shortcuts) if shortcut_context is not None: action.setShortcutContext(shortcut_context) if tooltip is not None: action.setToolTip(tooltip) action.setStatusTip(tooltip) if checkable: action.setCheckable(True) if checked: action.setChecked(True) if slot is not None: action.triggered.connect(slot) return action class Settings(): WIDTH = 20 HEIGHT = 15 NUM_BLOCKS_X = 10 NUM_BLOCKS_Y = 14 class QS(QtWidgets.QGraphicsScene): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) width = Settings.NUM_BLOCKS_X * Settings.WIDTH height = Settings.NUM_BLOCKS_Y * Settings.HEIGHT self.setSceneRect(0, 0, width, height) self.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex) class QV(QtWidgets.QGraphicsView): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.view_menu = QMenu(self) self.create_actions() def create_actions(self): act = create_action(self.view_menu, "Zoom in", slot=self.on_zoom_in, shortcut=QKeySequence("+"), shortcut_context=Qt.WidgetShortcut) self.view_menu.addAction(act) act = create_action(self.view_menu, "Zoom out", slot=self.on_zoom_out, shortcut=QKeySequence("-"), shortcut_context=Qt.WidgetShortcut) self.view_menu.addAction(act) self.addActions(self.view_menu.actions()) def on_zoom_in(self): if not self.scene(): return self.scale(1.5, 1.5) def on_zoom_out(self): if not self.scene(): return self.scale(1.0 / 1.5, 1.0 / 1.5) def drawBackground(self, painter, rect): gr = rect.toRect() start_x = gr.left() + Settings.WIDTH - (gr.left() % Settings.WIDTH) start_y = gr.top() + Settings.HEIGHT - (gr.top() % Settings.HEIGHT) painter.save() painter.setPen(QtGui.QColor(60, 70, 80).lighter(90)) painter.setOpacity(0.7) for x in range(start_x, gr.right(), Settings.WIDTH): painter.drawLine(x, gr.top(), x, gr.bottom()) for y in range(start_y, gr.bottom(), Settings.HEIGHT): painter.drawLine(gr.left(), y, gr.right(), y) painter.restore() super().drawBackground(painter, rect) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) a = QS() b = QV() b.setScene(a) # b.resize(800,600) b.show() sys.exit(app.exec_()),python,python-3.x,pyqt,Python,Python 3.x,Pyqt,如果我们运行它,我们可以看到网格块的数量是正常的,如指定的,它是8x10: 现在,假设我设置了NUM_BLOCKS\u X=3和NUM_BLOCKS\u Y=2,输出结果如下: 那是错误的!我绝对不希望这样,我希望QGraphicsView能够正确地收缩到我指定的网格设置 第一个问题:我如何才能做到这一点 另一个我想知道的是,让我们考虑一下格子为10x8的发布片段,然后让QGrICICSWIDGET调整为800×600,输出将是: 但我想知道我如何才能只画出qgraphicscene区域。

如果我们运行它,我们可以看到网格块的数量是正常的,如指定的,它是8x10:

现在,假设我设置了
NUM_BLOCKS\u X=3
NUM_BLOCKS\u Y=2
,输出结果如下:

那是错误的!我绝对不希望这样,我希望QGraphicsView能够正确地收缩到我指定的网格设置

第一个问题:我如何才能做到这一点

另一个我想知道的是,让我们考虑一下格子为10x8的发布片段,然后让QGrICICSWIDGET调整为800×600,输出将是:

但我想知道我如何才能只画出qgraphicscene区域。现在我正在牵引地面中使用
rect

所以我的第二个问题是:我如何只在Qgraphicscene的区域内绘制网格


缩小时会出现一个主要问题,在这种情况下,我只希望看到QGraphicscene的大小,因为我将只在该区域添加项目,我们称之为“可绘制”区域。如您所见,现在它正在“不可绘制”区域上绘制网格线,这确实令人困惑

您可以从库中获得自动调整大小的网格:

grid = QtGui.QGridLayout ()


您可以设置边框颜色。它实际上是小部件的对齐工具,但也许可以根据您的需要调整它

我会在场景中绘制网格,如下所示:

class QS(QtWidgets.QGraphicsScene):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        width = Settings.NUM_BLOCKS_X * Settings.WIDTH
        height = Settings.NUM_BLOCKS_Y * Settings.HEIGHT
        self.setSceneRect(0, 0, width, height)
        self.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex)

        for x in range(0,Settings.NUM_BLOCKS_X+1):
            xc = x * Settings.WIDTH
            self.addLine(xc,0,xc,height)

        for y in range(0,Settings.NUM_BLOCKS_Y+1):
            yc = y * Settings.HEIGHT
            self.addLine(0,yc,width,yc)
编辑: 其他可见性/不透明度功能:

class QS(QtWidgets.QGraphicsScene):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.lines = []

        self.draw_grid()
        self.set_opacity(0.3)
        #self.set_visible(False)
        #self.delete_grid()

    def draw_grid(self):
        width = Settings.NUM_BLOCKS_X * Settings.WIDTH
        height = Settings.NUM_BLOCKS_Y * Settings.HEIGHT
        self.setSceneRect(0, 0, width, height)
        self.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex)

        pen = QPen(QColor(255,0,100), 1, Qt.SolidLine)

        for x in range(0,Settings.NUM_BLOCKS_X+1):
            xc = x * Settings.WIDTH
            self.lines.append(self.addLine(xc,0,xc,height,pen))

        for y in range(0,Settings.NUM_BLOCKS_Y+1):
            yc = y * Settings.HEIGHT
            self.lines.append(self.addLine(0,yc,width,yc,pen))

    def set_visible(self,visible=True):
        for line in self.lines:
            line.setVisible(visible)

    def delete_grid(self):
        for line in self.lines:
            self.removeItem(line)
        del self.lines[:]

    def set_opacity(self,opacity):
        for line in self.lines:
            line.setOpacity(opacity)
您需要添加导入:
从PyQt5.QtGui导入QPen、QColor

EDIT2: 在场景中绘制矩形:

def draw_insert_at_marker(self):
    w = Settings.WIDTH * 3
    h = Settings.HEIGHT

    r = QRectF(7 * Settings.WIDTH, 7 * Settings.HEIGHT, w, h)
    gradient = QLinearGradient(r.topLeft(), r.bottomRight())
    gradient.setColorAt(1, QColor(255, 255, 255, 0))
    gradient.setColorAt(0, QColor(255, 255, 255, 127))
    rect = self.addRect(r, Qt.white, gradient)

您在视图中而不是在场景中绘制有什么原因吗?当前方案似乎没有利用视图/场景体系结构的任何好处。你也可以在一个通用的
QWidget
的背景上画画(尽管你现在也会遇到同样的问题)。如果答案在场景中绘制网格,可以吗?我对你真正想要的东西有点困惑(或者你可能不完全理解PyQt是如何工作的)。在任何情况下,使用QGraphicsView作为顶级小部件(因此也是一个窗口)都会让事情变得一团糟。在实际的应用程序中,您可能会在窗口中与其他窗口小部件一起使用视图,并可能使用严格的布局对其进行约束。或者,更好的是,如果您希望小部件具有固定的维度,那么可以直接输入小部件的维度。如果你让它不受约束,当然如果你调整窗口大小,它会调整大小,特别是当它是一个顶级小部件时。这并不能回答问题。QGridLayout
QGridLayout
不是绘画设备,因此您不能在其上绘制边框或其他任何东西。在编辑的答案中添加了一些函数来完成此操作。光标项是指水平的三个正方形吗?这到底是什么?不要在Graphicscene的背景中绘制,而是添加一个矩形:您还可以设置它的zvalue等。我更新了答案-请参见EDIT2。在绘制栅格图形后执行此操作时,不需要设置任何Z值。