程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了在小部件上绘制形状大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决在小部件上绘制形状?

开发过程中遇到在小部件上绘制形状的问题如何解决?下面主要结合日常开发的经验,给出你关于在小部件上绘制形状的解决方法建议,希望对你解决在小部件上绘制形状有所启发或帮助;

我需要能够在另一个小部件的顶部绘制圆/线,但每次尝试时,它都会落后。我已经阅读了很多关于在小部件上使用 QPainter 的帖子,但我仍然无法让它工作。

以下是我的应用程序的一个最小示例,我只想弄清楚将paintevent函数放在哪里才能使其正常工作。

我的最终目标是让用户能够绘制像这样的热数独 - thermo

但我认为,如果我能想出如何在数独网格上绘制任何东西,我就能解决剩下的问题

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *


class SudokuCell(QlineEdit):
    def __init__(self,cell_size,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.cell_size = cell_size
        Font = self.Font()
        Font.setPointSize(24)
        self.setFont(Font)
        self.setAlignment(Qt.AlignCenter)
        self.setFixedSize(cell_size,cell_sizE)
        self.setautoFillBACkground(true)

class SudokuRegion(QWidget):
    def __init__(self,narrow_line_wIDth,**kwargs)
        self.cell_size = cell_size
        self.narrow_line_wIDth = narrow_line_wIDth

        layout = qgridLayout()
        layout.setSpacing(narrow_line_wIDth)
        layout.setContentsmargins(0,0)
        self.setLayout(layout)

        for i in range(3):
            for j in range(3):
                new_cell = SudokuCell(cell_size,objectname=f"C{i}{j}")
                layout.addWidget(new_cell,i,j)
                               
class SudokuGrID(QWidget):
    def __init__(self,wIDe_line_wIDth,**kwargs)
        self.cell_size = cell_size
        self.wIDe_line_wIDth = wIDe_line_wIDth
        self.narrow_line_wIDth = narrow_line_wIDth

        layout = qgridLayout()
        layout.setContentsmargins(wIDe_line_wIDth,0)
        layout.setSpacing(wIDe_line_wIDth)
        self.setLayout(layout)

        for i in range(3):
            for j in range(3):
                new_region = SudokuRegion(cell_size,objectname=f"Region{i * 3 + j}")
                layout.addWidget(new_region,j)

class MainWindow(QMainWindow):
    def __init__(self,window_w,window_h,orthogonal_intersection_size,narrow_line_wIDth):
        super().__init__()
        self.window_w = window_w
        self.window_h = window_h
        self.orthogonal_intersection_size = orthogonal_intersection_size
        self.cell_size = cell_size
        self.wIDe_line_wIDth = wIDe_line_wIDth
        self.narrow_line_wIDth = narrow_line_wIDth

        # a sudoku grID is exactly this large. Google A sudoku grID if you dont understand
        self.frame_size = 9 * cell_size + 4 * wIDe_line_wIDth + 6 * narrow_line_wIDth
        self.initUi()

    def initUi(self):
        self.setwindowtitle("Sudoku Solver")
        self.setGeometry(100,100,self.window_w,self.window_h)

        Widget = QWidget(self)
        self.setCentralWidget(Widget)

        hor_Box = QHBoxLayout()
        Widget.setLayout(hor_BoX)

        self.frame = qframe(Widget)
        self.frame.setFixedSize(self.frame_size,self.frame_sizE)
        self.frame.setStyleSheet(".qframe {BACkground-color: black}")

        self.grID = SudokuGrID(self.cell_size,self.wIDe_line_wIDth,self.narrow_line_wIDth,self.framE)
        hor_Box.addWidget(self.framE)

        # other Widgets are added to the hor_Box later but arent important for this question
        self.show()

def main():
    app = QApplication(sys.argv)
    window = MainWindow(
        window_w=1000,window_h=750,orthogonal_intersection_size=25,cell_size=80,wIDe_line_wIDth=8,narrow_line_wIDth=2
    )
    window.show()
    app.exec_()

if __name__ == "__main__":
    main()

解决方法

您可以在 SudokuCell 或 SudokuGrid 中重新实现 paintEvent,但在任何一种情况下,SudokuCell 都需要具有透明背景,以便热绘图将绘制在除 QLineEdit 文本编辑器之外的所有内容之上。我选择了数独细胞。

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class SudokuCell(QLineEdit):
    def __init__(self,cell_size,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.cell_size = cell_size
        font = self.font()
        font.setPointSize(24)
        self.setFont(font)
        self.setAlignment(Qt.AlignCenter)
        self.setFixedSize(cell_size,cell_sizE)
        self.setAutoFillBACkground(true)

        self.setStyleSheet('''
        SudokuCell {
            BACkground-color: rgba(0,0);
            border: none;
        }''')
        self.line = QPainterPath()
        self.ellipse = false
        
    def paintEvent(self,event):
        qp = QPainter(self)
        qp.setPen(Qt.NoPen)
        qp.setBrush(Qt.whitE)
        qp.drawRect(self.rect())
        s = self.cell_size
        if self.ellipse:
            qp.setRenderHint(QPainter.Antialiasing)
            qp.setBrush(Qt.gray)
            qp.drawEllipse(self.rect().center(),s / 2.5,s / 2.5)
        qp.setPen(QPen(Qt.gray,s / 2,Qt.SolidLine,Qt.FlatCap,Qt.MiterJoin))
        qp.drawPath(self.linE)
        super().paintEvent(event)

请注意,super().paintEvent(event) 在自定义绘画之后被调用,因此文本编辑器将在任何绘画的顶部可见。如果背景为白色,它将覆盖自定义绘画。 SudokuGrid 类具有向由行和列指定的任何单元格添加线或椭圆的方法。

class SudokuGrid(QWidget):
    ...

    def cell(self,row,col):
        region = self.layout().itemAtPosition(row // 3,col // 3).widget()
        return region.layout().itemAtPosition(row % 3,col % 3).widget()

    def add_ellipse(self,col):
        self.cell(row,col).ellipse = True

    def add_line(self,col,*linE):
        path = QPainterPath(QPointF(*line[0]) * self.cell_sizE)
        for point in line[1:]:
            path.lineTo(QPointF(*point) * self.cell_sizE)
        self.cell(row,col).line = path

*lineSudokuGrid.add_line() 参数旨在是 0-1 范围内的元组,作为定义 QPainterPath 行元素的简单键(类似于渐变的元素 — 0 = 左/上,0.5 = 中心,1 = 右/下)。

class MainWindow(QMainWindow):
    def __init__(self,window_w,window_h,orthogonal_intersection_size,wide_line_width,narrow_line_width):
        super().__init__()
        self.window_w = window_w
        self.window_h = window_h
        self.orthogonal_intersection_size = orthogonal_intersection_size
        self.cell_size = cell_size
        self.wide_line_width = wide_line_width
        self.narrow_line_width = narrow_line_width

        # a sudoku grid is exactly this large. Google A sudoku grid if you dont understand
        self.frame_size = 9 * cell_size + 4 * wide_line_width + 6 * narrow_line_width
        self.initUi()

        self.grid.add_line(0,(0.25,0.5),(1,0.5))
        self.grid.add_line(0,1,(0,2,(0.5,1))
        self.grid.add_line(1,0),1))
        self.grid.add_line(2,0.5))
        self.grid.add_ellipse(2,2)

这里是它在 MainWindow 中的使用方式。当然,您可以采用更适合您的程序的完全不同的方式将线条和椭圆添加到网格中,主要目的是展示如何在“小部件顶部”实现绘画。

大佬总结

以上是大佬教程为你收集整理的在小部件上绘制形状全部内容,希望文章能够帮你解决在小部件上绘制形状所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: