Question

I'm using PyQt4 with Python 2.7 on Windows and for a music player, I decided to replace Phonon.SeekSlider with a QDial.
My problem is, that the minimum value of a QDial is always at the bottom of the dial, but I want it to be at the top (value still increasing clockwise). I tried setInvertedAppearance() and setInvertedControls(), but that just flips the dial horizontally and setOrientation() didn't help either.
My Question: Is there some way to either specify an angle to position the minimum value on the dial or flip the whole dial vertically?

Was it helpful?

Solution

I don't believe there is a way to do this directly. However, you can place the QDial in a QGraphicsView, and rotate it as an item in the scene. Something like this should work:

import sys
from PyQt4 import QtGui, QtCore

class RotatableView(QtGui.QGraphicsView):
    def __init__(self, item, rotation=0):
        QtGui.QGraphicsView.__init__(self)
        scene = QtGui.QGraphicsScene(self)
        self.setScene(scene)
        graphics_item = scene.addWidget(item)
        graphics_item.rotate(rotation)

        # make the QGraphicsView invisible
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setFixedHeight(item.height())
        self.setFixedWidth(item.width())
        self.setStyleSheet("border: 0px")

class DialExample(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        dial = QtGui.QDial()
        dial.setNotchesVisible(True)
        label = QtGui.QLabel('0')
        dial.valueChanged.connect(label.setNum)

        layout = QtGui.QVBoxLayout()
        layout.addWidget(RotatableView(dial, 180))
        layout.addWidget(label)
        self.setLayout(layout)

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    dialexample = DialExample()
    dialexample.show()
    sys.exit(app.exec_())

OTHER TIPS

Hackyday give a QgraphicsView answer, here I give you a pyqt solution without using QgraphicsView. You can do it directly on python with a little if/else statement.

You create your qDial, I suppose that you want a dial as a compass (0 - 360°) and I suppose you wrote the output of qDial on a qSpinBox):

<widget class="QDial" name="dial">
 <property name="geometry">
  <rect>
   <x>20</x>
   <y>150</y>
   <width>101</width>
   <height>111</height>
  </rect>
 </property>
 <property name="mouseTracking">
  <bool>false</bool>
 </property>
 <property name="acceptDrops">
  <bool>false</bool>
 </property>
 <property name="layoutDirection">
  <enum>Qt::LeftToRight</enum>
 </property>
 <property name="minimum">
  <number>0</number>
 </property>
 <property name="maximum">
  <number>360</number>
 </property>
 <property name="singleStep">
  <number>0</number>
 </property>
 <property name="pageStep">
  <number>0</number>
 </property>
 <property name="value">
  <number>135</number>
 </property>
 <property name="sliderPosition">
  <number>135</number>
 </property>
 <property name="orientation">
  <enum>Qt::Horizontal</enum>
 </property>
 <property name="invertedAppearance">
  <bool>false</bool>
 </property>
 <property name="invertedControls">
  <bool>false</bool>
 </property>
 <property name="wrapping">
  <bool>true</bool>
 </property>
 <property name="notchesVisible">
  <bool>false</bool>
 </property>
</widget>


<widget class="QSpinBox" name="oAzimuth">
 <property name="geometry">
  <rect>
   <x>10</x>
   <y>110</y>
   <width>52</width>
   <height>30</height>
  </rect>
 </property>
 <property name="maximum">
  <number>360</number>
 </property>
 <property name="value">
  <number>315</number>
 </property>
</widget>

If you want to set your default location of slider to 315° so, set it to 135° as in my example. Why ? Because all your degrees between 0° and 180° have to be shift to +180° and the degrees between 181° and 360° to -180°.

So on pyqt, on your file.py, you can write and if/else statement to correct that automatically inside a function:

def Edit_Slider(self):
    if self.dockwidget.spinbox.value() > 180:
         self.dockwidget.dial.setValue(self.dockwidget.spinbox.value()-180)
    else:
         self.dockwidget.dial.setValue(self.dockwidget.spinbox.value()+180)

def Edit_Spinbox(self):
    if self.dockwidget.dial.value() > 180:
         self.dockwidget.spinbox.setValue(self.dockwidget.dial.value()-180)
    else:
         self.dockwidget.spinbox.setValue(self.dockwidget.dial.value()+180)

And to edit this change automatically while you moved your slider or your SpinValue :

self.dockwidget.spinbox.valueChanged.connect(self.Edit_Slider)
self.dockwidget.dial.valueChanged.connect(self.Edit_Spinbox)

you also can use qdial value in the linedit. As the QDial works on Integers only, by using following commands you can use any value in float. self.dial_object = QtGui.QDial(self.centralwidget) self.dial_object.setNotchesVisible(True) self.dial_object.setGeometry(QtCore.QRect(15,110,45,45)) self.dial_object.setMinimum(50) this sets dial minimum value to .5 self.dial_object.setMaximum(100) this sets dial maximum value to 1 self.dial_object.setSingleStep(10) this sets dial resolution value to .01 self.dial_object.setValue(0) this sets dial starting value to 0 self.dial_object.valueChanged.connect(self.dvalue1) where def dvalue1(self): self.lineEdit_object.setText(str(float(self.dial_object.value())*0.01)) this will change the value into float to string type(used in setText). 0.01 decides the dials resolution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top