【问题标题】:round edges corner on a QWidget in PyQtPyQt中QWidget上的圆角
【发布时间】:2014-01-15 03:23:34
【问题描述】:

我在 PyQt4 中制作了一个 greadient QWidget,但是我想要圆边而不是锐边,是否可以在 pyqt 中做?

from PyQt4 import QtGui, QtCore
import sys

class ControlBar(QtGui.QWidget):
    """ docstring for ControlBar"""
    def __init__(self, parent=None):
        super(ControlBar, self).__init__(parent)
        self.resize(440, 100)
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.setWindowTitle("QLinearGradient Vertical Gradient ")
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.buildUi()

    def mousePressEvent(self, event):
        self.offset = event.pos()

    def mouseMoveEvent(self, event):
        try:
              x=event.globalX()
              y=event.globalY()
              x_w = self.offset.x()
              y_w = self.offset.y()
              self.move(x-x_w, y-y_w)
        except: pass   

    def paintEvent(self, ev):
        painter = QtGui.QPainter(self)
        gradient = QtGui.QLinearGradient(QtCore.QRectF(self.rect()).topLeft(),QtCore.QRectF(self.rect()).bottomLeft())
        gradient.setColorAt(0.0, QtCore.Qt.black)
        gradient.setColorAt(0.4, QtCore.Qt.gray)
        gradient.setColorAt(0.7, QtCore.Qt.black)
        painter.setBrush(gradient)
        painter.drawRoundedRect(0, 0, 440, 100, 20.0, 20.0)

    def buildUi(self):
        self.hoelayout = QtGui.QHBoxLayout()
        self.openBtn = RoundEdgeButton("Hello")
        self.backBtn = RoundEdgeButton()
        self.pausBtn = RoundEdgeButton()
        self.nextBtn = RoundEdgeButton()
        self.hoelayout.addStretch(1)
        self.hoelayout.addWidget(self.openBtn)
        self.hoelayout.addStretch(1)
        self.hoelayout.addWidget(self.backBtn)
        self.hoelayout.addStretch(1)
        self.hoelayout.addWidget(self.pausBtn)
        self.hoelayout.addStretch(1)
        self.hoelayout.addWidget(self.nextBtn)
        self.hoelayout.addStretch(1)
        self.setLayout(self.hoelayout)

class RoundEdgeButton(QtGui.QPushButton):
    """ docstring for RoundEdgeButton"""
    def __init__(self,text=None, parent=None):
        super(RoundEdgeButton, self).__init__(parent)

        if text:
            self.setText(text)

    def paintEvent(self, ev):
        btnPaint = QtGui.QPainter(self)
        btnGradient = QtGui.QLinearGradient(QtCore.QRectF(self.rect()).topLeft(), QtCore.QRectF(self.rect()).bottomLeft())
        btnGradient.setColorAt(0.8, QtCore.Qt.black)
        btnGradient.setColorAt(0.1, QtCore.Qt.gray)
        btnGradient.setColorAt(0.8, QtCore.Qt.black)
        btnPaint.setBrush(btnGradient)
        btnPaint.drawRoundedRect(self.rect(), 100.0, 100.0)


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    win = ControlBar()
    win.show()
    win.raise_()
    sys.exit(app.exec_())

这是现在的样子

【问题讨论】:

  • 我已经更新了半透明按钮的答案
  • btnPaint.drawRoundedRect(0, 0, 50, 50, 100.0, 100.0) 更改为btnPaint.drawRoundedRect(self.rect(), 100.0, 100.0)
  • 我们遗漏了一些东西,为什么它们会在中间被压扁以形成椭圆形,我知道 rect() 是 QRect(0, 0 , 75, 32) 但是将这个值手动输入到 drawRoundedRect 会放大按钮,但它仍然在中间被剪掉......
  • 如果您尝试使用较小的圆半径会怎样,例如btnPaint.drawRoundedRect(self.rect(), 10.0, 10.0)
  • 您可以将def sizeHint(self): return QtCore.QSize(100,27) 添加到您的RoundEdgeButton 课程中。

标签: python pyqt pyqt4 pyside pyqt5


【解决方案1】:

您可以使用QPainter.drawRoundedRect 自己绘制小部件的区域:

from PyQt4.QtGui import * 
from PyQt4.QtCore import * 
import sys


class MyRoundWidget(QWidget):

    def __init__(self, master=None):
        super(MyRoundWidget,self).__init__(master)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setWindowTitle("QLinearGradient Vertical Gradient ")
        self.setAttribute(Qt.WA_TranslucentBackground)


    def paintEvent(self, ev):
        painter = QPainter(self)
        painter.begin(self)
        gradient = QLinearGradient(QRectF(self.rect()).topLeft(),QRectF(self.rect()).bottomLeft())
        gradient.setColorAt(0.0, Qt.black)
        gradient.setColorAt(0.4, Qt.gray)
        gradient.setColorAt(0.7, Qt.black)
        painter.setBrush(gradient)
        painter.drawRoundedRect(self.rect(), 10.0, 10.0)
        painter.end()


def main():    

    app     = QApplication(sys.argv)
    widget = MyRoundWidget()    

    widget.show()
    widget.raise_()



    sys.exit(app.exec_())
if __name__ == '__main__':
    main()

为了使按钮半透明,这样做:

self.setStyleSheet("""
        QPushButton{
        opacity: 50;            
        background-color: rgba(204,204,204,10);
        }
        """)

0255 之间将10 更改为您喜欢的值。

如果您只想要圆形按钮(不是圆形矩形按钮),请将 btnPaint.drawRoundedRect(self.rect(), 100.0, 100.0) 替换为 btnPaint.drawEllipse(10,10,self.width()-10, self.height()-10)

【讨论】:

  • 是这个黑魔法在终端中导致了这个QPainter::begin: A paint device can only be painted by one painter at a time. 吗?
  • @san 是的,就像我说的正确的做法是子类化QWidget,我稍后会重构答案:)
  • 仍然收到QPainter::begin: Painter already active 消息,我想知道为什么?
  • 是的,我也添加了按钮,但是按钮的尖角看起来很难看,我将在问题中更新上面的代码
  • 我已经实现了一个按钮不能正确显示的点,我重新实现了 QPushButton,并将它们变成圆形,就像你对小部件所做的那样,但是位置和渐变没有显示正确..再次更新代码。
【解决方案2】:

painter = QPainter(self) 如果构造了QPainter对象,那么就不需要调用begin()和end()了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2020-02-28
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 2013-10-21
    相关资源
    最近更新 更多