<legend id='1Znsb'><style id='1Znsb'><dir id='1Znsb'><q id='1Znsb'></q></dir></style></legend>
      <tfoot id='1Znsb'></tfoot>

          <bdo id='1Znsb'></bdo><ul id='1Znsb'></ul>
      1. <small id='1Znsb'></small><noframes id='1Znsb'>

        <i id='1Znsb'><tr id='1Znsb'><dt id='1Znsb'><q id='1Znsb'><span id='1Znsb'><b id='1Znsb'><form id='1Znsb'><ins id='1Znsb'></ins><ul id='1Znsb'></ul><sub id='1Znsb'></sub></form><legend id='1Znsb'></legend><bdo id='1Znsb'><pre id='1Znsb'><center id='1Znsb'></center></pre></bdo></b><th id='1Znsb'></th></span></q></dt></tr></i><div id='1Znsb'><tfoot id='1Znsb'></tfoot><dl id='1Znsb'><fieldset id='1Znsb'></fieldset></dl></div>
      2. 将小部件旋转一定程度

        时间:2024-08-11

        <tfoot id='K9k7q'></tfoot>

          <small id='K9k7q'></small><noframes id='K9k7q'>

          <legend id='K9k7q'><style id='K9k7q'><dir id='K9k7q'><q id='K9k7q'></q></dir></style></legend>

              <i id='K9k7q'><tr id='K9k7q'><dt id='K9k7q'><q id='K9k7q'><span id='K9k7q'><b id='K9k7q'><form id='K9k7q'><ins id='K9k7q'></ins><ul id='K9k7q'></ul><sub id='K9k7q'></sub></form><legend id='K9k7q'></legend><bdo id='K9k7q'><pre id='K9k7q'><center id='K9k7q'></center></pre></bdo></b><th id='K9k7q'></th></span></q></dt></tr></i><div id='K9k7q'><tfoot id='K9k7q'></tfoot><dl id='K9k7q'><fieldset id='K9k7q'></fieldset></dl></div>
                <tbody id='K9k7q'></tbody>
                <bdo id='K9k7q'></bdo><ul id='K9k7q'></ul>
                1. 本文介绍了将小部件旋转一定程度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我是pyqt新手,需要帮助旋转标签。我很困惑,无法理解如何以特定的角度旋转整个小部件。不是小部件的内容,而是小部件本身。我正在搜索解决方案,但什么也找不到。

                  推荐答案

                  正如@eyllanesc正确解释的那样,Qt中不支持"小部件轮换"(与大多数标准框架一样)。

                  不过,您手上有几个小把戏。

                  "简单"标签(不使用QLabel)

                  这是"简单"的解决方案。由于您谈论的是"标签",因此可以使用一些数学运算来实现。

                  此方法最大的优点是大小提示"简单",即它只基于文本内容(如QFontMetrics.boundingRect()),只要更改了主要字体、文本或对齐方式,大小提示就会反映它们。
                  虽然它支持多行标签,但是如果您需要使用富文本,这种方法最大的问题就出现在这里;QTextDocument可以用来代替标准字符串,但这将需要更复杂的大小提示计算实现。

                  from math import radians, sin, cos
                  from random import randrange
                  
                  from PyQt5 import QtCore, QtGui, QtWidgets
                  
                  class AngledLabel(QtWidgets.QWidget):
                      _alignment = QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop
                  
                      def __init__(self, text='', angle=0, parent=None):
                          super(AngledLabel, self).__init__(parent)
                          self._text = text
                          self._angle = angle % 360
                          # keep radians of the current angle *and* its opposite; we're using
                          # rectangles to get the overall area of the text, and since they use
                          # right angles, that opposite is angle + 90
                          self._radians = radians(-angle)
                          self._radiansOpposite = radians(-angle + 90)
                  
                      def alignment(self):
                          return self._alignment
                  
                      def setAlignment(self, alignment):
                          # text alignment might affect the text size!
                          if alignment == self._alignment:
                              return
                          self._alignment = alignment
                          self.setMinimumSize(self.sizeHint())
                  
                      def angle(self):
                          return self._angle
                  
                      def setAngle(self, angle):
                          # the angle clearly affects the overall size
                          angle %= 360
                          if angle == self._angle:
                              return
                          self._angle = angle
                          # update the radians to improve optimization of sizeHint and paintEvent
                          self._radians = radians(-angle)
                          self._radiansOpposite = radians(-angle + 90)
                          self.setMinimumSize(self.sizeHint())
                  
                      def text(self):
                          return self._text
                  
                      def setText(self, text):
                          if text == self._text:
                              return
                          self._text = text
                          self.setMinimumSize(self.sizeHint())
                  
                      def sizeHint(self):
                          # get the bounding rectangle of the text
                          rect = self.fontMetrics().boundingRect(QtCore.QRect(), self._alignment, self._text)
                          # use trigonometry to get the actual size of the rotated rectangle
                          sinWidth = abs(sin(self._radians) * rect.width())
                          cosWidth = abs(cos(self._radians) * rect.width())
                          sinHeight = abs(sin(self._radiansOpposite) * rect.height())
                          cosHeight = abs(cos(self._radiansOpposite) * rect.height())
                          return QtCore.QSize(cosWidth + cosHeight, sinWidth + sinHeight)
                  
                      def minimumSizeHint(self):
                          return self.sizeHint()
                  
                      def paintEvent(self, event):
                          qp = QtGui.QPainter(self)
                          textRect = self.fontMetrics().boundingRect(
                              QtCore.QRect(), self._alignment, self._text)
                          width = textRect.width()
                          height = textRect.height()
                          # we have to translate the painting rectangle, and that depends on which
                          # "angle sector" the current angle is
                          if self._angle <= 90:
                              deltaX = 0
                              deltaY = sin(self._radians) * width
                          elif 90 < self._angle <= 180:
                              deltaX = cos(self._radians) * width
                              deltaY = sin(self._radians) * width + sin(self._radiansOpposite) * height
                          elif 180 < self._angle <= 270:
                              deltaX = cos(self._radians) * width + cos(self._radiansOpposite) * height
                              deltaY = sin(self._radiansOpposite) * height
                          else:
                              deltaX = cos(self._radiansOpposite) * height
                              deltaY = 0
                          qp.translate(.5 - deltaX, .5 - deltaY)
                          qp.rotate(-self._angle)
                          qp.drawText(self.rect(), self._alignment, self._text)
                  
                  
                  class TestWindow(QtWidgets.QWidget):
                      def __init__(self):
                          super(TestWindow, self).__init__()
                          layout = QtWidgets.QGridLayout()
                          self.setLayout(layout)
                  
                          self.randomizeButton = QtWidgets.QPushButton('Randomize!')
                          layout.addWidget(self.randomizeButton, 0, 0, 1, 3)
                          self.randomizeButton.clicked.connect(self.randomize)
                  
                          layout.addWidget(QtWidgets.QLabel('Standard label'), 1, 0)
                          text = 'Some text'
                          layout.addWidget(QtWidgets.QLabel(text), 1, 2)
                          self.labels = []
                          for row, angle in enumerate([randrange(360) for _ in range(8)], 2):
                              angleLabel = QtWidgets.QLabel(u'{}°'.format(angle))
                              angleLabel.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
                              layout.addWidget(angleLabel, row, 0)
                              label = AngledLabel(text, angle)
                              layout.addWidget(label, row, 2)
                              self.labels.append((angleLabel, label))
                  
                          separator = QtWidgets.QFrame()
                          separator.setFrameShape(separator.VLine|separator.Sunken)
                          layout.addWidget(separator, 1, 1, layout.rowCount() - 1, 1)
                  
                      def randomize(self):
                          for angleLabel, label in self.labels:
                              angle = randrange(360)
                              angleLabel.setText(str(angle))
                              label.setAngle(angle)
                          self.adjustSize()
                  
                  
                  if __name__ == '__main__':
                      import sys
                      app = QtWidgets.QApplication(sys.argv)
                      w = TestWindow()
                      w.show()
                      sys.exit(app.exec_())
                  

                  QGraphicsView实现

                  我还想扩展eyllanesc提出的解决方案,因为它更加模块化,并且允许使用"任何"小部件;不幸的是,尽管他的答案如预期的那样工作,但我担心这只是一个"为了论证"而有效的答案。
                  从图形的角度来看,最明显的问题是QGraphicsView视觉提示(边框和背景)。但是,由于我们讨论的是可能必须插入到图形界面中的小部件,因此需要注意大小(及其提示)。 这种方法的主要优点是,几乎任何类型的小部件都可以添加到界面,但是由于每个小部件大小策略和QGraphicsView实现的性质,如果"旋转"的小部件的内容发生变化,完美的绘制总是很难实现的。

                  from random import randrange
                  from PyQt5 import QtCore, QtGui, QtWidgets
                  
                  class AngledObject(QtWidgets.QGraphicsView):
                      _angle = 0
                  
                      def __init__(self, angle=0, parent=None):
                          super(AngledObject, self).__init__(parent)
                          # to prevent the graphics view to draw its borders or background, set the
                          # FrameShape property to 0 and a transparent background
                          self.setFrameShape(0)
                          self.setStyleSheet('background: transparent')
                          self.setScene(QtWidgets.QGraphicsScene())
                          # ignore scroll bars!
                          self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
                          self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
                          self.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
                  
                      def angle(self):
                          return self._angle
                  
                      def setAngle(self, angle):
                          angle %= 360
                          if angle == self._angle:
                              return
                          self._angle = angle
                          self._proxy.setTransform(QtGui.QTransform().rotate(-angle))
                          self.adjustSize()
                  
                      def resizeEvent(self, event):
                          super(AngledObject, self).resizeEvent(event)
                          # ensure that the scene is fully visible after resizing
                          QtCore.QTimer.singleShot(0, lambda: self.centerOn(self.sceneRect().center()))
                  
                      def sizeHint(self):
                          return self.scene().itemsBoundingRect().size().toSize()
                  
                      def minimumSizeHint(self):
                          return self.sizeHint()
                  
                  
                  class AngledLabel(AngledObject):
                      def __init__(self, text='', angle=0, parent=None):
                          super(AngledLabel, self).__init__(angle, parent)
                          self._label = QtWidgets.QLabel(text)
                          self._proxy = self.scene().addWidget(self._label)
                          self._label.setStyleSheet('background: transparent')
                          self.setAngle(angle)
                          self.alignment = self._label.alignment
                  
                      def setAlignment(self, alignment):
                          # text alignment might affect the text size!
                          if alignment == self._label.alignment():
                              return
                          self._label.setAlignment(alignment)
                          self.setMinimumSize(self.sizeHint())
                  
                      def text(self):
                          return self._label.text()
                  
                      def setText(self, text):
                          if text == self._label.text():
                              return
                          self._label.setText(text)
                          self.setMinimumSize(self.sizeHint())
                  
                  
                  class AngledButton(AngledObject):
                      def __init__(self, text='', angle=0, parent=None):
                          super(AngledButton, self).__init__(angle, parent)
                          self._button = QtWidgets.QPushButton(text)
                          self._proxy = self.scene().addWidget(self._button)
                          self.setAngle(angle)
                  
                  
                  class TestWindow(QtWidgets.QWidget):
                      def __init__(self):
                          super(TestWindow, self).__init__()
                          layout = QtWidgets.QGridLayout()
                          self.setLayout(layout)
                  
                          self.randomizeButton = QtWidgets.QPushButton('Randomize!')
                          layout.addWidget(self.randomizeButton, 0, 0, 1, 3)
                          self.randomizeButton.clicked.connect(self.randomize)
                  
                          layout.addWidget(QtWidgets.QLabel('Standard label'), 1, 0)
                          text = 'Some text'
                          layout.addWidget(QtWidgets.QLabel(text), 1, 2)
                          self.labels = []
                          for row, angle in enumerate([randrange(360) for _ in range(4)], 2):
                              angleLabel = QtWidgets.QLabel(u'{}°'.format(angle))
                              angleLabel.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
                              layout.addWidget(angleLabel, row, 0)
                              label = AngledLabel(text, angle)
                              layout.addWidget(label, row, 2)
                              self.labels.append((angleLabel, label))
                  
                          for row, angle in enumerate([randrange(360) for _ in range(4)], row + 1):
                              angleLabel = QtWidgets.QLabel(u'{}°'.format(angle))
                              angleLabel.setSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
                              layout.addWidget(angleLabel, row, 0)
                              label = AngledButton('Button!', angle)
                              layout.addWidget(label, row, 2)
                              self.labels.append((angleLabel, label))
                  
                          separator = QtWidgets.QFrame()
                          separator.setFrameShape(separator.VLine|separator.Sunken)
                          layout.addWidget(separator, 1, 1, layout.rowCount() - 1, 1)
                  
                      def randomize(self):
                          for angleLabel, label in self.labels:
                              angle = randrange(360)
                              angleLabel.setText(str(angle))
                              label.setAngle(angle)
                          self.adjustSize()
                  
                  
                  if __name__ == '__main__':
                      import sys
                      app = QtWidgets.QApplication(sys.argv)
                      w = TestWindow()
                      w.show()
                      sys.exit(app.exec_())
                  

                  如您所见,"随机化"函数有非常不同的结果。虽然第二种方法允许使用更复杂的小部件,但第一种方法可以更好地响应内容更改。

                  这篇关于将小部件旋转一定程度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:PyQt:如何创建自定义组合标题栏和菜单栏 下一篇:PyQt:如何使用QAxWidget引用发送参数

                  相关文章

                  1. <legend id='VS9Ft'><style id='VS9Ft'><dir id='VS9Ft'><q id='VS9Ft'></q></dir></style></legend>
                    <tfoot id='VS9Ft'></tfoot>

                      <i id='VS9Ft'><tr id='VS9Ft'><dt id='VS9Ft'><q id='VS9Ft'><span id='VS9Ft'><b id='VS9Ft'><form id='VS9Ft'><ins id='VS9Ft'></ins><ul id='VS9Ft'></ul><sub id='VS9Ft'></sub></form><legend id='VS9Ft'></legend><bdo id='VS9Ft'><pre id='VS9Ft'><center id='VS9Ft'></center></pre></bdo></b><th id='VS9Ft'></th></span></q></dt></tr></i><div id='VS9Ft'><tfoot id='VS9Ft'></tfoot><dl id='VS9Ft'><fieldset id='VS9Ft'></fieldset></dl></div>

                      <small id='VS9Ft'></small><noframes id='VS9Ft'>

                        <bdo id='VS9Ft'></bdo><ul id='VS9Ft'></ul>