# Linear and Rotary controls These are intended to show MIDI CC values, hence the default min,max of 0..127. ## Linear ```python from PySide6.QtCore import * from PySide6.QtGui import * from PySide6.QtWidgets import * from rtmidi import MidiIn, MidiOut import sys import math def radians(x): return x*math.pi/180 def degrees(x): return x*180/math.pi app = QApplication([]) # Define Widgets class Linear(QWidget): def __init__(self): super().__init__() self.value = 45 self.maxval = 127 self.minval = 0 self.mx = 0 self.my = 0 def mousePressEvent(self,e): self.mval = self.value pos = e.pos() self.mx = pos.x() self.my = pos.y() print(f"press {pos.x()} {pos.y()}") def mouseMoveEvent(self,e): pos = e.pos() dy = - (pos.y() - self.my) self.value = max(min(self.mval + dy,self.maxval),self.minval) print(f"move {pos.x()} {pos.y()} -- {dy=}") self.update() def paintEvent(self, event: QPaintEvent): """Override method from QWidget Paint the Pixmap into the widget """ rect = self.rect() w = rect.width() h = rect.height() w1 = w*0.9 h1 = h*0.9 cx = w/2 cy = h/2 m = min(w,h) r = (m/2) * 0.9 y0 = cy - h1/2 font = QFont("Arial",r/4) metrics = QFontMetrics(font) t = str(self.value) twidth = metrics.horizontalAdvance(t) theight = metrics.capHeight() tx = cx-(twidth/2) ty = cy+(theight/2) svalue = (self.value-self.minval)/(self.maxval-self.minval) with QPainter(self) as painter: painter.fillRect(rect,Qt.white) painter.setBrush(Qt.NoBrush) path = QPainterPath() path.moveTo(QPoint(cx,y0+h1)) path.lineTo(QPoint(cx,y0)) painter.setPen(QPen(Qt.black, 5)) painter.drawPath(path) path.clear() path.moveTo(QPoint(cx,y0+h1)) path.lineTo(QPoint(cx,y0+h1*(1-svalue))) painter.setPen(QPen(Qt.red,10)) painter.drawPath(path) painter.setFont(font) painter.drawText(QPoint(tx,ty),t) # Instantiate Widgets linear = Linear() linear.show() # Loader def main(): exit(app.exec()) if __name__ == "__main__": main() ``` ## Rotary ```python from PySide6.QtCore import * from PySide6.QtGui import * from PySide6.QtWidgets import * from rtmidi import MidiIn, MidiOut import sys import math def radians(x): return x*math.pi/180 def degrees(x): return x*180/math.pi app = QApplication([]) # Define Widgets class Rotary(QWidget): def __init__(self): super().__init__() self.value = 45 self.maxval = 127 self.minval = 0 self.mx = 0 self.my = 0 def mousePressEvent(self,e): self.mval = self.value pos = e.pos() self.mx = pos.x() self.my = pos.y() print(f"press {pos.x()} {pos.y()}") def mouseMoveEvent(self,e): pos = e.pos() dy = - (pos.y() - self.my) self.value = max(min(self.mval + dy,self.maxval),self.minval) print(f"move {pos.x()} {pos.y()} -- {dy=}") self.update() def paintEvent(self, event: QPaintEvent): """Override method from QWidget Paint the Pixmap into the widget """ rect = self.rect() w = rect.width() h = rect.height() cx = w/2 cy = h/2 m = min(w,h) r = (m/2) * 0.9 x = cx - r y = cy - r ww = 2*r wh = 2*r wr = QRect(QPoint(x,y),QSize(ww,wh)) wtheta = 300 itheta = 270-((360-wtheta)//2) dtheta = wtheta*(self.value/(self.maxval-self.minval)) font = QFont("Arial",r/2) metrics = QFontMetrics(font) t = str(self.value) twidth = metrics.horizontalAdvance(t) theight = metrics.capHeight() tx = cx-(twidth/2) ty = cy+(theight/2) with QPainter(self) as painter: painter.fillRect(rect,Qt.white) path = QPainterPath() path.arcMoveTo(wr,itheta) path.arcTo(wr,itheta,-dtheta) painter.setBrush(Qt.NoBrush) painter.setPen(QPen(Qt.black, 5)) painter.drawPath(path) painter.setFont(font) painter.drawText(QPoint(tx,ty),t) # Instantiate Widgets rotary = Rotary() rotary.show() # Loader def main(): exit(app.exec()) if __name__ == "__main__": main() ``` ## Linear2 Illustrates how to use modifiers like shift and control (note `mods.value` and `Qt.ShiftModifier.value` if you want to bitwise compare), and have shift do fine-grained movements, and control jumping straight to the mouse position. ```python from PySide6.QtCore import * from PySide6.QtGui import * from PySide6.QtWidgets import * from rtmidi import MidiIn, MidiOut import sys import math def radians(x): return x*math.pi/180 def degrees(x): return x*180/math.pi app = QApplication([]) # Define Widgets class LinearSlider1(QWidget): def __init__(self): super().__init__() self.value = 45 self.maxval = 127 self.minval = 0 self.mx = 0 self.my = 0 self.ly = 0 self.lv = 0 self.sens = 1 # scales so that dragging the height of the widget goes from min to max def mousePressEvent(self,e): self.mval = self.value pos = e.pos() self.mx = pos.x() self.my = pos.y() self.ly = self.my self.lv = self.value mods = e.modifiers() if mods == Qt.ControlModifier: return self.mouseMoveAbsolute(e) print(f"press {pos.x()} {pos.y()}") def mouseMoveAbsolute(self,e): rect = self.rect() h = rect.height() pos = e.pos() y = pos.y() x = 1 - y/h self.value = self.minval + x*(self.maxval - self.minval) self.value = min(self.maxval,max(self.minval,self.value)) self.lv = self.value self.ly = y self.value = int(self.value) self.update() def mouseMoveEvent(self,e): mods = e.modifiers() sens = self.sens if mods == Qt.ControlModifier: return self.mouseMoveAbsolute(e) if mods.value & Qt.ShiftModifier.value: print("shift") sens /= 10 rect = self.rect() h = rect.height() pos = e.pos() dy = - (pos.y() - self.ly) self.ly = pos.y() dy1 = sens*(dy / h)*(self.maxval - self.minval) print("aa",self.lv,dy1) self.lv = max(min(dy1+self.lv,self.maxval),self.minval) self.value = int(self.lv) self.update() return dy = - (pos.y() - self.my) rect = self.rect() h = rect.height() dy1 = sens*(dy / h)*(self.maxval-self.minval) print(f"{h=} {dy=} {dy1=}") self.value = int(max(min(self.mval + dy1,self.maxval),self.minval)) print(f"move {pos.x()} {pos.y()} -- {dy=}") self.update() def paintEvent(self, event: QPaintEvent): """Override method from QWidget Paint the Pixmap into the widget """ rect = self.rect() w = rect.width() h = rect.height() w1 = w h1 = h cx = w/2 cy = h/2 m = min(w,h) r = (m/2) y0 = cy - h1/2 font = QFont("Arial",r/4) metrics = QFontMetrics(font) t = str(self.value) twidth = metrics.horizontalAdvance(t) theight = metrics.capHeight() tx = cx-(twidth/2) ty = cy+(theight/2) svalue = (self.value-self.minval)/(self.maxval-self.minval) with QPainter(self) as painter: painter.fillRect(rect,Qt.white) painter.setBrush(Qt.NoBrush) path = QPainterPath() path.moveTo(QPoint(cx,y0+h1)) path.lineTo(QPoint(cx,y0)) painter.setPen(QPen(Qt.black, 5)) painter.drawPath(path) path.clear() path.moveTo(QPoint(cx,y0+h1)) path.lineTo(QPoint(cx,y0+h1*(1-svalue))) painter.setPen(QPen(Qt.red,10)) painter.drawPath(path) painter.setFont(font) painter.drawText(QPoint(tx,ty),t) # Instantiate Widgets slider = LinearSlider1() slider.show() # Loader def main(): exit(app.exec()) if __name__ == "__main__": main() ```