0

pyside(python / Qt)で最初のプロトタイプを試しています。アプリケーション自体は正常に起動し、私のレイアウトに従ってウィジェットを含むウィンドウを作成します。スレッドが開始され、実行されます。すべて正常です。それ外...

スレッドの実行状態を示すカスタムウィジェットを追加して、GUIを強化したいと思います。だから、LEDを点滅させるのはそれでいいと思いました。このために、私はカスタムLEDウィジェットを実装しようとします。

私は現在Pythonを学ぼうとしているので、これには奇妙なアプローチがあるかもしれません。とにかく、これが現在の状態のLEDウィジェットクラスです。

from PySide import QtCore, QtGui

class LED(QtGui.QWidget):

    class Mode:
        STATIC_OFF   = 0
        STATIC_ON    = 1
        FLASH_SLOW   = 2
        FLASH_MEDIUM = 2
        FLASH_FAST   = 3

    class Color:
        BLACK  = '#000000'
        GREEN  = '#00FF00'
        RED    = '#FF0000'
        BLUE   = '#0000FF'
        YELLOW = '#FFFF00' 
        WHITE  = '#FFFFFF'

    mode   = Mode.STATIC_ON
    color  = Color.BLACK
    radius = 10
    status = False
    timer  = None

    outdated = QtCore.Signal()

    def __init__(self, mode, color, radius, parent=None):
        super(LED, self).__init__(parent)
        self.outdated.connect(self.update)
        self.setMode(mode,False)
        self.setColor(color,False)
        self.setRadius(radius,False)
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.adjustAppearance)
        self.adjustAppearance()

    def getCenter(self):
        return QtCore.QPoint(self.radius, self.radius)

    def getBox(self):
        return QtCore.QRect(self.radius, self.radius)

    def setColor(self, color, update=True):
        assert color in (self.Color.GREEN,self.Color.RED,self.Color.BLUE,self.Color.YELLOW,self.Color.WHITE), "invalid color"
        self.color = color
        if update:
            self.adjustAppearance()

    def setMode(self, mode, update=True):
        assert mode in (self.Mode.STATIC_OFF,self.Mode.STATIC_ON,self.Mode.FLASH_SLOW,self.Mode.FLASH_MEDIUM,self.Mode.FLASH_FAST),"invalid mode"
        self.mode = mode
        if update:
            self.adjustAppearance()

    def setRadius(self, radius, update=True):
        assert isinstance(radius, int), "invalid radius type (integer)"
        assert 10<=radius<=100, "invalid radius value (0-100)"
        self.radius = radius
        if update:
            self.adjustAppearance()

    def switchOn(self):
        self.status = True
        self.adjustAppearance()

    def switchOff(self):
        self.status = False
        self.adjustAppearance()

    def adjustAppearance(self):
        if self.mode is self.Mode.STATIC_OFF:
            self.status = False
            self.timer.stop()
        elif self.mode is self.Mode.STATIC_ON:
            self.status = True
            self.timer.stop()
        elif self.mode is self.Mode.FLASH_SLOW:
            self.status = not self.status
            self.timer.start(200)
        elif self.mode is self.Mode.FLASH_SLOW:
            self.status = not self.status
            self.timer.start(500)
        elif self.mode is self.Mode.FLASH_SLOW:
            self.status = not self.status
            self.timer.start(1000)
            self.outdated.emit()

    def paintEvent(self, event):
        painter = QtGui.QPainter()
        painter.begin(self)
        self.drawWidget(event, painter)
        painter.end()

    def drawWidget(self, event, painter):
        if self.status:
            shade = QtGui.QColor(self.color).darker
        else:
            shade = QtGui.QColor(self.color).lighter
        #painter.setPen(QtGui.QColor('black'), 1, QtCore.Qt.SolidLine)
        painter.setPen(QtGui.QColor('black'))
        painter.setBrush(QtCore.Qt.RadialGradientPattern)
        painter.drawEllipse(self.getCenter(), self.radius, self.radius)

私の問題は、ウィジェットをWindowsレイアウトに追加すると、ウィジェットが表示されないことです。他のウィジェット(非カスタムのプレーンQtウィジェット)は表示されるので、ウィジェットの作成の問題ではなく、ウィジェットの使用方法の問題ではないと思います。それにもかかわらず、ウィジェットが次の場合の(短縮された)インスタンス化は次のとおりです。

class View(QtGui.QMainWindow):

    ui = None

    def __init__(self, config, parent=None):
        log.debug("window setup")
        self.config = config
        super(View, self).__init__(parent)
        try:
            self.ui = self.Ui(self)
            self.setObjectName("appView")
            self.setWindowTitle("AvaTalk")
            self.show()
        except RuntimeError as e:
            log.error(e.message)

    class Ui(QtCore.QObject):

        # [...]
        iconDetector = None
        buttonDetector = None
        # [...]

        def __init__(self, window, parent=None):
            log.debug("ui setup")
            super(View.Ui, self).__init__(parent)
            self.window = window

            # central widget
            log.debug("widget setup")
            self.centralWidget = QtGui.QWidget()
            self.widgetLayout = QtGui.QVBoxLayout(self.centralWidget)

            # create toolbars
            #self.createMenubar()
            #self.createCanvas()
            self.createToolbar()
            #self.createStatusbar()

            # visualize widget
            self.window.setCentralWidget(self.centralWidget)

            # actions
            log.debug("actions setup")
            self.actionQuit = QtGui.QAction(self.window)
            self.actionQuit.setObjectName("actionQuit")
            self.menuFile.addAction(self.actionQuit)
            self.menubar.addAction(self.menuFile.menuAction())

            log.debug("connections setup")
            QtCore.QObject.connect(self.actionQuit, QtCore.SIGNAL("activated()"), self.window.close)
            QtCore.QMetaObject.connectSlotsByName(self.window)

        def createToolbar(self):
            log.debug("toolbar setup")
            self.toolbar = QtGui.QHBoxLayout()
            self.toolbar.setObjectName("toolbar")
            self.toolbar.addStretch(1)
            # camera
            # detector
            self.iconDetector = LED(LED.Mode.STATIC_OFF,LED.Color.GREEN,10,self.window)
            self.buttonDetector = IconButton("Detector", "detector",self.window)
            self.toolbar.addWidget(self.iconDetector)
            self.toolbar.addWidget(self.buttonDetector)
            self.toolbar.addStretch(1)
            # analyzer
            # extractor
            # layout
            self.widgetLayout.addLayout(self.toolbar)

QPainterを使用した実際のペイントはまだナンセンスである可能性があります。私はまだそれをテストするようになりませんでした。実際にテストすると、セットアップが完了した後にウィジェットにisVisible()戻ることがわかりました。Falseだから私は中心点を逃していると思います。残念ながら、私は私が見逃しているものを見つけることができません...

多分誰かが私の問題を見つけることができますか?ありがとう !

4

1 に答える 1

2

から派生したカスタム ウィジェットを実装する際に注意すべきことの 1 つQWidgetsizeHint、 orがデフォルトで無効minimumSizeHintQWidget返すことです。QSizeこれは、レイアウトに追加された場合、他のウィジェットに応じて縮小されることを意味し0ます。これにより、効果的に「非表示」になります。ただし、isVisibleそれでも返されTrueます。ウィジェットは「表示」されていますが、表示するものが何もありません (0 サイズ)。したがって、 を取得Falseしている場合は、間違いなく別の問題が発生しています。

したがって、適切なサイズでこれら 2 つのメソッドを定義する必要があります。

class LED(QtGui.QWidget):
    # ...

    def sizeHint(self):
        size = 2 * self.radius + 2
        return QtCore.QSize(size, size)

    def minimumSizeHint(self):
        size = 2 * self.radius + 2
        return QtCore.QSize(size, size)

注: 他にも次の問題があります。

  • 、などをクラス属性として定義modeし、colorそれらをインスタンス属性でオーバーライドするのと同じです。それらは何も壊しませんが、無意味です。
  • painter.setBrush(QtCore.Qt.RadialGradientPattern)間違っている。でブラシを作成することはできませんQtCore.Qt.RadialGradientPattern。それはそこにあるので、brush.style()何かを返すことができます。グラデーション パターンが必要な場合は、QGradientコンストラクターでブラシを作成する必要があります。
  • if self.mode is self.Mode.STATIC_OFF: との比較isは間違っています。isID を比較し==ます。ここで必要です。(また、FLASH_SLOWFLASH_MEDIUMは両方とも2)
  • assertデバッグおよび単体テスト用です。実際のコードでは使用しないでください。必要に応じて例外を発生させます。defaultまたは、無効な値がそれに置き換えられる賢明なs があります。
于 2013-02-24T10:49:48.140 に答える