Trouble with updating text in QLabel - python

So I'm making a music player and I want a section where can see my songs, Page by page. The page switching works but the text doesn't update. I've tried googleing but i coudn't find a fitting/working anwser. For the people that want it, this is what my idle says:
1
0
2
3
n1
n2
1
1
2
3
Anyway here is my code:
import sys
import os
import pygame
from PyQt4 import QtGui, QtCore
from time import sleep
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle("Music Player Alpha")
AutoPlay = True
Song = os.listdir('/home/pi/Desktop/Muziek/' )
Song = sorted(Song)
self.Song = Song
self.CurrentSong = 0
self.PageNum = 0
pygame.mixer.init()
pygame.mixer.music.load('/home/pi/Desktop/Muziek/' + Song[0])
pygame.mixer.music.play()
self.home()
def home(self):
print("1")
print(self.PageNum)
btnQuit = QtGui.QPushButton("Quit", self)
btnQuit.clicked.connect(self.close)
btnQuit.move(400,270)
btnPlay = QtGui.QPushButton("Play", self)
btnPlay.clicked.connect(self.play)
btnPlay.move(100, 270)
btnPause = QtGui.QPushButton("Pause", self)
btnPause.clicked.connect(self.pause)
btnPause.move(200, 270)
btnNext = QtGui.QPushButton("Next", self)
btnNext.clicked.connect(self.next)
btnNext.move(300, 270)
btnPrevious = QtGui.QPushButton("Previous", self)
btnPrevious.clicked.connect(self.previous)
btnPrevious.move(0, 270)
btnPrevPage = QtGui.QPushButton("Prev Page", self)
btnPrevPage.clicked.connect(self.PrevPage)
btnPrevPage.move(0,160)
btnNextPage = QtGui.QPushButton("Next Page", self)
btnNextPage.clicked.connect(self.NextPage)
btnNextPage.move(100, 160)
try:
txtNum1 = QtGui.QLabel(self.Song[0 + 10*self.PageNum], self)
txtNum1.resize(500, 30)
txtNum2 = QtGui.QLabel(self.Song[1 + 10*self.PageNum], self)
txtNum2.move(0, 15)
txtNum2.resize(500, 30)
txtNum3 = QtGui.QLabel(self.Song[2 + 10*self.PageNum], self)
txtNum3.move(0, 30)
txtNum3.resize(500, 30)
txtNum4 = QtGui.QLabel(self.Song[3 + 10*self.PageNum], self)
txtNum4.move(0, 45)
txtNum4.resize(500, 30)
txtNum5 = QtGui.QLabel(self.Song[4 + 10*self.PageNum], self)
txtNum5.move(0, 60)
txtNum5.resize(500, 30)
txtNum6 = QtGui.QLabel(self.Song[5 + 10*self.PageNum], self)
txtNum6.move(0, 75)
txtNum6.resize(500, 30)
txtNum7 = QtGui.QLabel(self.Song[6 + 10*self.PageNum], self)
txtNum7.move(0, 90)
txtNum7.resize(500, 30)
txtNum8 = QtGui.QLabel(self.Song[7 + 10*self.PageNum], self)
txtNum8.move(0, 105)
txtNum8.resize(500, 30)
txtNum9 = QtGui.QLabel(self.Song[8 + 10*self.PageNum], self)
txtNum9.move(0, 120)
txtNum9.resize(500, 30)
txtNum10 = QtGui.QLabel(self.Song[9 + 10*self.PageNum], self)
txtNum10.move(0, 135)
txtNum10.resize(500, 30)
print("2")
except IndexError:
print("2.5")
self.show()
print("3")
def close(self):
sys.exit()
def play(self):
pygame.mixer.music.unpause()
def pause(self):
pygame.mixer.music.pause()
def next(self, event):
self.CurrentSong = self.CurrentSong + 1
if self.CurrentSong > len(self.Song) + 1:
self.CurrentSong = 0
pygame.mixer.music.load('/home/pi/Desktop/Muziek/' + self.Song[self.CurrentSong])
pygame.mixer.music.play()
return self.CurrentSong;
def previous(self, event):
self.CurrentSong = self.CurrentSong - 1
if self.CurrentSong < 0:
self.CurrentSong = len(self.Song) -1
pygame.mixer.music.load('/home/pi/Desktop/Muziek/' + self.Song[self.CurrentSong])
pygame.mixer.music.play()
def PrevPage(self, event):
print("p1")
self.PageNum = self.PageNum - 1
if self.PageNum < 0 :
print("p<0")
self.PageNum = 0
print("p2")
self.home()
return self.PageNum;
def NextPage(self, event):
print("n1")
self.PageNum = self.PageNum + 1
if self.PageNum > len(self.Song) / 10:
print("n>0")
self.PageNum = self.PageNum - 1
print("n2")
self.home()
return self.PageNum;
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())

The problem is that every time you call the home() function you are creating new labels, what you have to do is just update the text, for this we create a list of labels. Avoid using try and except since the program may have errors, it is better to verify that the index of the list is in the range.
When closing the window it is better to release the sound resource with pygame.mixer.quit() before closing the window, for this it is better to overwrite closeEvent().
import sys
import os
import pygame
from PyQt4 import QtGui, QtCore
from time import sleep
class Window(QtGui.QMainWindow):
song_per_page = 10
directory = '/home/pi/Desktop/Muziek/'
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle("Music Player Alpha")
AutoPlay = True
Song = os.listdir(self.directory)
Song = sorted(Song)
self.Song = Song
self.CurrentSong = 0
self.PageNum = 0
pygame.mixer.init()
self.txtNums = []
self.home()
self.song()
def home(self):
btnQuit = QtGui.QPushButton("Quit", self)
btnQuit.clicked.connect(self.close)
btnQuit.move(400, 270)
btnPlay = QtGui.QPushButton("Play", self)
btnPlay.clicked.connect(self.play)
btnPlay.move(100, 270)
btnPause = QtGui.QPushButton("Pause", self)
btnPause.clicked.connect(self.pause)
btnPause.move(200, 270)
btnNext = QtGui.QPushButton("Next", self)
btnNext.clicked.connect(self.next)
btnNext.move(300, 270)
btnPrevious = QtGui.QPushButton("Previous", self)
btnPrevious.clicked.connect(self.previous)
btnPrevious.move(0, 270)
btnPrevPage = QtGui.QPushButton("Prev Page", self)
btnPrevPage.clicked.connect(self.PrevPage)
btnPrevPage.move(0, 160)
btnNextPage = QtGui.QPushButton("Next Page", self)
btnNextPage.clicked.connect(self.NextPage)
btnNextPage.move(100, 160)
for i in range(self.song_per_page):
txtNum = QtGui.QLabel(self)
txtNum.resize(500, 30)
txtNum.move(0, 15 * i)
self.txtNums.append(txtNum)
self.updateLabels()
self.show()
def updateLabels(self):
print(self.CurrentSong, self.PageNum)
for i in range(len(self.txtNums)):
index = i + self.song_per_page * self.PageNum
self.txtNums[i].clear()
if index < len(self.Song):
self.txtNums[i].setText(self.Song[i + self.song_per_page * self.PageNum])
def closeEvent(self, event):
pygame.mixer.quit()
QtGui.QMainWindow.closeEvent(self, event)
def play(self):
pygame.mixer.music.unpause()
def pause(self):
pygame.mixer.music.pause()
def song(self):
try:
pygame.mixer.music.load(self.directory + self.Song[self.CurrentSong])
pygame.mixer.music.play()
except pygame.error:
print("Module format not recognized")
self.updateLabels()
def next(self, event):
self.CurrentSong = (self.CurrentSong + 1) % len(self.Song)
self.song()
def previous(self, event):
self.CurrentSong = (self.CurrentSong - 1) % len(self.Song)
self.song()
def PrevPage(self, event):
self.PageNum = self.PageNum - 1
if self.PageNum < 0:
self.PageNum = 0
self.updateLabels()
def NextPage(self, event):
if self.song_per_page * (self.PageNum + 1) - 1 < len(self.Song):
self.PageNum = self.PageNum + 1
self.updateLabels()
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())

Related

Widget selection problem with rubberband in 2 layouts

Currently, 2 layouts have been added, and buttons are added using FlowLayout at the top and below the label.
on Qrubberband
When the mouse is don't move, there is nothing wrong. When I drag, there is a problem with the selection.
Where did the problem come from?
# -*- coding: utf-8 -*-
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
class QToolButton(QToolButton):
def __init__(self, label='', icon='', icon_size=100):
super(QToolButton, self).__init__()
self.label = label
self.icon = icon
self.icon_size = icon_size
self.create()
def create(self):
self.setText(self.label)
self.setIcon(QIcon(self.icon))
self.setIconSize(QSize(self.icon_size, self.icon_size))
self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.setCheckable(True)
self.setFocusPolicy(Qt.NoFocus)
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
self.ui()
self.add_thumbnail()
def ui(self):
self.setContentsMargins(2, 2, 2, 2)
self.resize(1000, 800)
self.centralwidget = QWidget(self)
self.gridLayout = QGridLayout(self.centralwidget)
self.label = QLabel(self.centralwidget)
self.label.setText('LABEL IMAGE')
self.label.setMinimumSize(QSize(0, 100))
self.label.setMaximumSize(QSize(16777215, 100))
self.label.setAlignment(Qt.AlignCenter)
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.frame = QFrame(self.centralwidget)
self.frame.setFrameShape(QFrame.StyledPanel)
self.frame.setFrameShadow(QFrame.Raised)
self.gridLayout.addWidget(self.frame, 1, 0, 1, 1)
self.setCentralWidget(self.centralwidget)
self.flow_layout = FlowLayout()
self.frame.setLayout(self.flow_layout)
def add_thumbnail(self):
for i in range(10):
button = QToolButton(label='test', icon='test')
self.flow_layout.addWidget(button)
button.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == event.MouseButtonPress:
self.origin = source.mapTo(self, event.pos())
elif event.type() == event.MouseMove and event.buttons():
if not self.rubberBand.isVisible():
distance = (source.mapTo(self, event.pos()) - self.origin).manhattanLength()
if distance > QApplication.startDragDistance():
if isinstance(source, QAbstractButton) and source.isDown():
source.setDown(False)
self.rubberBand.show()
if self.rubberBand.isVisible():
self.resizeRubberBand(source.mapTo(self, event.pos()))
event.accept()
return True
elif event.type() == event.MouseButtonRelease and self.rubberBand.isVisible():
self.closeRubberBand()
event.accept()
return True
return super(Window, self).eventFilter(source, event)
def startRubberBand(self, pos):
self.origin = pos
self.rubberBand.setGeometry(
QRect(self.origin, QSize()))
self.rubberBand.show()
def resizeRubberBand(self, pos):
if self.rubberBand.isVisible():
self.rubberBand.setGeometry(
QRect(self.origin, pos).normalized())
def closeRubberBand(self):
if self.rubberBand.isVisible():
self.rubberBand.hide()
selected = []
rect = self.rubberBand.geometry()
for child in self.findChildren(QToolButton):
if rect.intersects(child.geometry()):
selected.append(child)
if selected:
for i in selected:
if i.isChecked():
i.setChecked(False)
else:
i.setChecked(True)
def mousePressEvent(self, event):
self.startRubberBand(event.pos())
QMainWindow.mousePressEvent(self, event)
def mouseMoveEvent(self, event):
self.resizeRubberBand(event.pos())
QMainWindow.mouseMoveEvent(self, event)
def mouseReleaseEvent(self, event):
self.closeRubberBand()
QMainWindow.mouseReleaseEvent(self, event)
class FlowLayout(QLayout):
def __init__(self, parent=None, margin=0, spacing=-1):
super(FlowLayout, self).__init__(parent)
if parent is not None:
self.setContentsMargins(margin, margin, margin, margin)
self.setSpacing(spacing)
self.margin = margin
# spaces between each item
self.spaceX = 2
self.spaceY = 2
self.itemList = []
def __del__(self):
item = self.takeAt(0)
while item:
item = self.takeAt(0)
def addItem(self, item):
self.itemList.append(item)
def count(self):
return len(self.itemList)
def itemAt(self, index):
if index >= 0 and index < len(self.itemList):
return self.itemList[index]
return None
def takeAt(self, index):
if index >= 0 and index < len(self.itemList):
return self.itemList.pop(index)
return None
def expandingDirections(self):
return Qt.Orientations(Qt.Orientation(0))
def hasHeightForWidth(self):
return True
def heightForWidth(self, width):
height = self.doLayout(QRect(0, 0, width, 0), True)
return height
def setGeometry(self, rect):
super(FlowLayout, self).setGeometry(rect)
self.doLayout(rect, False)
def sizeHint(self):
return self.minimumSize()
def minimumSize(self):
size = QSize()
for item in self.itemList:
size = size.expandedTo(item.minimumSize())
size += QSize(2 * self.margin, 2 * self.margin)
return size
def doLayout(self, rect, testOnly):
x = rect.x()
y = rect.y()
lineHeight = 0
for item in self.itemList:
wid = item.widget()
nextX = x + item.sizeHint().width() + self.spaceX
if nextX - self.spaceX > rect.right() and lineHeight > 0:
x = rect.x()
y = y + lineHeight + self.spaceY
nextX = x + item.sizeHint().width() + self.spaceX
lineHeight = 0
if not testOnly:
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
x = nextX
lineHeight = max(lineHeight, item.sizeHint().height())
return y + lineHeight - rect.y()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
Where did the problem come from?
When left-clicking the mouse, when it was mousePressEvent, it worked normally, and when it was mouseReleaseEvent, there was a problem with widget selection.
I have solved it now
the code is
def closeRubberBand(self):
if self.rubberBand.isVisible():
self.rubberBand.hide()
selected = []
rect = self.rubberBand.geometry()
for child in self.findChildren(QToolButton):
if self.flow_layout_widget:
layout_x = self.flow_layout_widget.pos().toTuple()[0]
layout_y = self.flow_layout_widget.pos().toTuple()[1]
child_w = child.geometry().size().toTuple()[0]
child_h = child.geometry().size().toTuple()[1]
cx, cy, cw, ch = (child.geometry().x() + layout_x, child.geometry().y() + layout_y, child_w, child_h)
child_rect = QRect(cx, cy, cw, ch)
else:
child_rect = child.geometry()
if rect.intersects(child_rect):
selected.append(child)
if selected:
for i in selected:
if i.isChecked():
i.setChecked(False)
else:
i.setChecked(True)
Could there be an easier way?

Why can't I use the mouse Event(mouseMoveEvent, mouseReleaseEvent) on the graphicsview?

I want to make cropping image tool by using python and pyqt5
Below code, I can't use the mouseMoveEvent and mouseReleaseEvent on
the graphic view.
But, I only can use the mousePressEvent on the graphicview. I checked the interactive about QGraphicView properties.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PIL import Image
from PyQt5 import uic
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
IS_RESULT = False
CROP_UI = uic.loadUiType("Image_crop_screen.ui")[0]
BRING_IN_IMG_ROUTE = "C:/Users/yoon/Desktop/test/test.jpg"
class MainScreen(QMainWindow, CROP_UI):
def __init__(self):
super().__init__()
self.setupUi(self)
# Graphic Screen set
self.img = QGraphicsPixmapItem(QPixmap(BRING_IN_IMG_ROUTE))
self.scene = QGraphicsScene()
self.scene.addItem(self.img)
self.graphicsView.setScene(self.scene)
self.graphicsView.pencolor = QColor(240, 240, 240)
self.graphicsView.brushcolor = QColor(255, 255, 255, 0)
QGV = QGraphicsView()
self.items = []
# Full Screen set size
_WIDTH_ADD = 25
_HEIGHT_ADD = 25
self.setGeometry(0, 0, 640 + _WIDTH_ADD, 500 + _HEIGHT_ADD)
def moveEvent(self, e):
rect = QRectF(self.rect())
rect.adjust(0, 0, 0, 0) # 창 스크롤 바 없애기 위해서 일부 크기 작게 설정
self.scene.setSceneRect(rect)
# Draw rectangular while moving mouse
def mouseMoveEvent(self, e):
# e.buttons()는 정수형 값을 리턴, e.button()은 move시 Qt.Nobutton 리턴
print(Qt.LeftButton)
print(e.buttons())
print(e)
if e.buttons() & Qt.LeftButton:
self.end = e.pos()
pen = QPen(self.parent().pencolor)
brush = QBrush(self.parent().brushcolor)
pen.setWidth(3)
# 장면에 그려진 이전 선을 제거
if len(self.items) > 0:
self.scene.removeItem(self.items[-1])
del (self.items[-1])
rect = QRectF(self.start, self.end)
self.items.append(self.scene.addRect(rect, pen, brush))
def mousePressEvent(self, e):
if e.button() == Qt.LeftButton:
# 시작점 저장
self.start = e.pos()
self.end = e.pos()
print(Qt.LeftButton)
print(e.buttons())
print(e)
def mouseReleaseEvent(self, e):
print("aaa2")
if e.button() == Qt.LeftButton:
global IS_RESULT
print("ttt2")
pen = QPen(self.parent().pencolor)
brush = QBrush(self.parent().brushcolor)
self.items.clear()
rect = QRectF(self.start, self.end)
self.scene.addRect(rect, pen, brush)
print("(" + str(self.start.x()) + ", " + str(self.start.y()) + "), (" + str(self.end.x()) + ", " + str(
self.end.y()) + ")")
area = (self.start.x(), self.start.y(), self.end.x(), self.end.y())
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainScreen()
w.show()
sys.exit(app.exec_())
If you want to listen to the events of the QGraphicsView you should not override the events of another widget since some events will not be transmitted. In this case it is better to use an event filter that tracks the mouse, in this case the events of the viewport() of the QGraphicsView should be monitored.
In the following example I show how to create rectangles with the mouse.
class MainScreen(QMainWindow, CROP_UI):
def __init__(self):
super().__init__()
self.setupUi(self)
# Graphic Screen set
self.img = QGraphicsPixmapItem(QPixmap(BRING_IN_IMG_ROUTE))
self.scene = QGraphicsScene()
self.scene.addItem(self.img)
self.graphicsView.setScene(self.scene)
# Full Screen set size
_WIDTH_ADD = 25
_HEIGHT_ADD = 25
self.setGeometry(0, 0, 640 + _WIDTH_ADD, 500 + _HEIGHT_ADD)
self.graphicsView.viewport().installEventFilter(self)
self.current_item = None
self.start_pos = QPointF()
self.end_pos = QPointF()
def eventFilter(self, o, e):
if self.graphicsView.viewport() is o:
if e.type() == QEvent.MouseButtonPress:
if e.buttons() & Qt.LeftButton:
print("press")
self.start_pos = self.end_pos = self.graphicsView.mapToScene(
e.pos()
)
pen = QPen(QColor(240, 240, 240))
pen.setWidth(3)
brush = QBrush(QColor(100, 255, 100, 100))
self.current_item = self.scene.addRect(QRectF(), pen, brush)
self._update_item()
elif e.type() == QEvent.MouseMove:
if e.buttons() & Qt.LeftButton and self.current_item is not None:
print("move")
self.end_pos = self.graphicsView.mapToScene(e.pos())
self._update_item()
elif e.type() == QEvent.MouseButtonRelease:
print("release")
self.end_pos = self.graphicsView.mapToScene(e.pos())
self._update_item()
self.current_item = None
return super().eventFilter(o, e)
def _update_item(self):
if self.current_item is not None:
self.current_item.setRect(QRectF(self.start_pos, self.end_pos).normalized())
You have to create a class with type QGraphicView in which you will use the mouse events
class MyGraphicView(QGraphicsView):
def __init__():
super.__init__(self)
self.myScene = QGraphicsScene()
self.setScene(self.myScene)
# the rest code
def mousePressEvent(self, event):
...
def mouseMoveEvent(self, event):
...
def mouseReleaseEvent(self, event):
...

How can I add pyqt5 buttons on top of each other?

I am trying to create a basic 25 key keyboard in pyqt, I have laid out the 15 white keys but am struggling with how to add the 10 remaining black keys,
This is how I made my keys
from PyQt5.QtWidgets import QApplication, QPushButton
app = QApplication([])
top_win = QWidget()
set_color(top_win, Qt.cyan)
top_win.setAutoFillBackground(True)
top_win.show()
top_win.resize(1920,1080)
top_win.setWindowTitle("Synth-01")
top_vlayout = QVBoxLayout()
top_win.setLayout(top_vlayout)
keyboard = QWidget()
keyboard.setMaximumWidth(1410)
top_vlayout.addWidget(keyboard)
keyboard_layout = QHBoxLayout()
keyboard.setAutoFillBackground(True)
keyboard.setLayout(keyboard_layout)
for i in range(15):
name = "key_" + str(i)
name = QPushButton()
name.setMaximumWidth(94)
name.setMaximumHeight(349)
keyboard_layout.addWidget(name)
I now want to add the black keys inbetween like this
In this case, it is most preferable to use QGraphicsScene with QGraphicsItem, for this case I will use svg:
from PyQt5 import QtCore, QtGui, QtWidgets, QtSvg
class PianoKey(QtWidgets.QGraphicsRectItem):
def __init__(self, black=False, rect = QtCore.QRectF(), parent=None):
super(PianoKey, self).__init__(rect, parent)
self.m_pressed = False
self.m_selectedBrush = QtGui.QBrush()
self.m_brush = QtGui.QBrush(QtCore.Qt.black) if black else QtGui.QBrush(QtCore.Qt.white)
self.m_black = black
def setPressedBrush(self, brush):
self.m_selectedBrush = brush
def paint(self, painter, option, widget):
rendered = QtSvg.QSvgRenderer("key.svg")
black_pen = QtGui.QPen(QtCore.Qt.black, 1)
gray_pen = QtGui.QPen(QtGui.QBrush(QtCore.Qt.gray), 1,
QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)
if self.m_pressed:
if self.m_selectedBrush.style() != QtCore.Qt.NoBrush:
painter.setBrush(self.m_selectedBrush)
else:
painter.setBrush(QtWidgets.QApplication.palette().highlight())
else:
painter.setBrush(self.m_brush);
painter.setPen(black_pen)
painter.drawRoundedRect(self.rect(), 15, 15, QtCore.Qt.RelativeSize)
if self.m_black:
rendered.render(painter, self.rect())
else:
points = [
QtCore.QPointF(self.rect().left()+1.5, self.rect().bottom()-1),
QtCore.QPointF(self.rect().right()-1, self.rect().bottom()-1),
QtCore.QPointF(self.rect().right()-1, self.rect().top()+1)
]
painter.setPen(gray_pen)
painter.drawPolyline(QtGui.QPolygonF(points))
def mousePressEvent(self, event):
self.m_pressed = True
self.update()
super(PianoKey, self).mousePressEvent(event)
event.accept()
def mouseReleaseEvent(self, event):
self.m_pressed = False
self.update()
super(PianoKey, self).mouseReleaseEvent(event)
KEYWIDTH, KEYHEIGHT = 18, 72
class PianoKeyBoard(QtWidgets.QGraphicsView):
def __init__(self, num_octaves=2, parent=None):
super(PianoKeyBoard, self).__init__(parent)
self.initialize()
self.m_numOctaves = num_octaves
scene = QtWidgets.QGraphicsScene(QtCore.QRectF(0, 0, KEYWIDTH * self.m_numOctaves * 7, KEYHEIGHT), self)
self.setScene(scene)
numkeys = self.m_numOctaves * 12
for i in range(numkeys):
octave = i//12*7
j = i % 12
if j >= 5: j += 1
if j % 2 == 0:
x = (octave + j/2)*KEYWIDTH
key = PianoKey(rect=QtCore.QRectF(x, 0, KEYWIDTH, KEYHEIGHT), black=False)
else:
x = (octave + j//2) * KEYWIDTH + KEYWIDTH * 6//10 + 1
key = PianoKey(rect=QtCore.QRectF(x, 0, KEYWIDTH * 8//10 - 1, KEYHEIGHT * 6//10 ), black=True)
key.setZValue(1)
key.setPressedBrush(QtWidgets.QApplication.palette().highlight())
self.scene().addItem(key)
def initialize(self):
self.setAttribute(QtCore.Qt.WA_InputMethodEnabled, False)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setCacheMode(QtWidgets.QGraphicsView.CacheBackground)
self.setViewportUpdateMode(QtWidgets.QGraphicsView.MinimalViewportUpdate)
self.setRenderHints(QtGui.QPainter.Antialiasing|
QtGui.QPainter.TextAntialiasing |
QtGui.QPainter.SmoothPixmapTransform)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontClipPainter, True)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontSavePainterState, True)
self.setOptimizationFlag(QtWidgets.QGraphicsView.DontAdjustForAntialiasing, True)
self.setBackgroundBrush(QtWidgets.QApplication.palette().base())
def resizeEvent(self, event):
super(PianoKeyBoard, self).resizeEvent(event)
self.fitInView(self.scene().sceneRect(), QtCore.Qt.KeepAspectRatio)
def sizeHint(self):
return self.mapFromScene(self.sceneRect()).boundingRect().size()
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyle('fusion')
w = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(w)
lay.addWidget(QtWidgets.QLabel("Piano Keyboard", alignment=QtCore.Qt.AlignCenter))
lay.addWidget(PianoKeyBoard())
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
The complete code + key.svg can be found on this link

updating qlabel after input waiting

I have seen some information posted about this, but everything seems to be with PyQt4 not PyQt5 and I'm not sure if there is a difference. I couldn't get anything to work.
What I want to do is have the program update a QLabel after the user inputs text into it and saves it. Right now I have the main window, with either a button or a selection from a drop down menu that will pop up a window with the ability to change setpoints.
Now what happens is the user can put in new data, but the code seems to still run and not wait for the user to make a change in the popup. calling my updateSetpoints function before anything changes.
# popups the reactorSetpoints window to change the setpoints for
# the reactor. This is where I am haiving troubles, the code
# continues before the user can input new setpoints
def reactorSetpoints(self):
exPopup = setpointsPopup(self)
self.updateSetpoints()
# just have it update the one value for now
def updateSetpoints(self):
self.pHUpperValue.setText(str(upper_pH))
A button calls reactorSetpoints(self) and popups a new window
import sys
import matplotlib.pyplot as plt
import random
from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication,QLineEdit, QPushButton, QWidget, QDialog, QTextEdit, QLabel, QMenu, QVBoxLayout, QSizePolicy
from PyQt5.QtGui import *
from PyQt5.QtCore import Qt, QTime, QTimer, QRect
from PyQt5 import QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
debug = True
setPointsChanged = False
versionNumber = 'V0.0.1'
currentState = 'Treatment'
currentCycTime = '2:15:42'
remaningCycTime = '5:44:18'
current_pH = 6.85
current_DO = 1.90
currentTemp = 24.9
lower_pH = 6.95
upper_pH = 7.20
lower_DO = 2.00
def openFile():
if debug == True:
print("Open File")
def saveFile():
if debug == True:
print("Save File")
def saveFileAs():
if debug == True:
print("Save File As...")
def editSysParm():
if debug == True:
print("Edit system parameters")
def reactorParameters():
if debug == True:
print("Edit reactor parameters")
def pHCalibration():
if debug == True:
print("pH Calibration")
def dOCalibration():
if debug == True:
print("DO calibration")
def pumpCalibration():
if debug == True:
print("Pump calibrations")
def editpHSetpoints():
pass
# sets up the setpoints popup window with either the option to save
# new setpoints, or to quit
class setpointsPopup(QDialog):
def __init__(self, parent = None):
super().__init__(parent)
self.initUI()
def initUI(self):
self.setGeometry(100,100,300,300)
self.upH = QLabel('Upper pH: ',self)
self.lpH = QLabel('Lower pH: ',self)
self.lDO = QLabel('Lower DO: ',self)
self.upHE = QLineEdit(self)
self.lpHE = QLineEdit(self)
self.lDOE = QLineEdit(self)
self.upHE.setPlaceholderText(str(upper_pH))
self.lpHE.setPlaceholderText(str(lower_pH))
self.lDOE.setPlaceholderText(str(lower_DO))
self.exitSetpoints = QPushButton('Exit', self)
self.saveSetpoints = QPushButton('Save New Setpoints', self)
self.upH.move(5,5)
self.upHE.move(90,5)
self.lpH.move(5,40)
self.lpHE.move(90,40)
self.lDO.move(5,75)
self.lDOE.move(90,75)
self.exitSetpoints.setGeometry(QRect(5,120,50,30))
self.exitSetpoints.clicked.connect(self.destroy)
self.saveSetpoints.setGeometry(QRect(60,120,150,30))
self.saveSetpoints.clicked.connect(self.verifySetpoints)
self.show()
#verification will be put here to make sure the input is valid
#but for now it will accept anything for ease of testing
def verifySetpoints(self):
global upper_pH
newUpH = self.upHE.text()
upper_pH = float(newUpH)
print(newUpH)
# Main window
class drawMenuBar(QMainWindow):
def __init__(self):
super().__init__()
self.topL = 20
self.top = 40
self.width = 1000
self.height = 500
self.title = ('Batch Reactor Controller ' + versionNumber)
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.topL, self.top, self.width, self.height)
exitAct = QAction('&Exit' , self)
exitAct.setShortcut('Ctrl+Q')
exitAct.setStatusTip('Exit Application')
exitAct.triggered.connect(qApp.quit)
openAct = QAction('&Open', self)
openAct.setShortcut('Ctrl+O')
openAct.setStatusTip('Open File')
openAct.triggered.connect(openFile)
saveAsAct = QAction('&Save As..', self)
saveAsAct.setShortcut('Shift+Ctrl+S')
saveAsAct.setStatusTip('Save as new file')
saveAsAct.triggered.connect(saveFileAs)
saveAct = QAction('Save', self)
saveAct.setStatusTip('Save')
saveAct.setShortcut('Ctrl+S')
saveAct.triggered.connect(saveFile)
systemSetpointsAct = QAction('Preferences', self)
systemSetpointsAct.setStatusTip('Edit system parameters')
systemSetpointsAct.triggered.connect(editSysParm)
reactorSetpointsAct = QAction('Reactor Setpoints', self)
reactorSetpointsAct.setStatusTip('Edit reactor setpoints')
reactorSetpointsAct.triggered.connect(self.reactorSetpoints)
reactorParametersAct = QAction('Reactor Parameters', self)
reactorParametersAct.setStatusTip('Edit batch reactor profiles')
reactorParametersAct.triggered.connect(reactorParameters)
pHCalibrationAct = QAction('pH Calibration', self)
pHCalibrationAct.setStatusTip('pH Calibration')
pHCalibrationAct.triggered.connect(pHCalibration)
dOCalibrationAct = QAction('DO Calibration', self)
dOCalibrationAct.setStatusTip('Dissolved oxygen calibration')
dOCalibrationAct.triggered.connect(dOCalibration)
pumpCalibrationAct = QAction('Pump Calibrations', self)
pumpCalibrationAct.setStatusTip('Pump Calibrations')
pumpCalibrationAct.triggered.connect(pumpCalibration)
menubar = self.menuBar()
self.statusBar()
fileMenu = menubar.addMenu('&File')
editMenu = menubar.addMenu('&Edit')
calibrationMenu = menubar.addMenu('&Calibration')
fileMenu.addAction(openAct)
fileMenu.addAction(saveAct)
fileMenu.addAction(saveAsAct)
fileMenu.addAction(exitAct)
calibrationMenu.addAction(pHCalibrationAct)
calibrationMenu.addAction(dOCalibrationAct)
calibrationMenu.addAction(pumpCalibrationAct)
editMenu.addAction(systemSetpointsAct)
editMenu.addAction(reactorSetpointsAct)
self.reactorTitle = QLabel('<b><u>Reactor 1 Status</u></b>', self)
font = self.reactorTitle.font()
font.setPointSize(20)
self.reactorTitle.setFont(font)
self.reactorTitle.setGeometry(QtCore.QRect(10,30, 250, 45)) #(x, y, width, height)
#pH Label
self.pHLabel = QLabel('<span style="color:blue"><b>pH:</b></span>',self)
font = self.pHLabel.font()
font.setPointSize(22)
self.pHLabel.setFont(font)
self.pHLabel.setGeometry(QtCore.QRect(10,50,100,100))
#displays current pH value
self.currentpH = QLabel('<b>' + str(current_pH) + '</b>', self)
font = self.currentpH.font()
font.setPointSize(22)
self.currentpH.setFont(font)
self.currentpH.setGeometry(QtCore.QRect(60,50,100,100))
#display lowerpH Setpoint
self.pHLowerLabel = QLabel('Lower pH setpoint: ', self)
font = self.pHLowerLabel.font()
font.setPointSize(10)
self.pHLowerLabel.setFont(font)
self.pHLowerLabel.setGeometry(QtCore.QRect(10, 105, 115, 50))
self.pHLowerValue = QLabel('{0:0.2f}'.format(lower_pH), self)
font = self.pHLowerValue.font()
font.setPointSize(10)
self.pHLowerValue.setFont(font)
self.pHLowerValue.setGeometry(QtCore.QRect(120, 105, 50, 50))
#display upper pH setpoint
self.pHUpperLabel = QLabel('Upper pH setpoint: ', self)
font = self.pHUpperLabel.font()
font.setPointSize(10)
self.pHUpperLabel.setFont(font)
self.pHUpperLabel.setGeometry(QtCore.QRect(10, 120, 115, 50))
self.pHUpperValue = QLabel('{0:0.2f}'.format(upper_pH), self)
font = self.pHUpperValue.font()
font.setPointSize(10)
self.pHUpperValue.setFont(font)
self.pHUpperValue.setGeometry(QtCore.QRect(120, 120, 50, 50))
#pH button options
self.pHToGraph = QPushButton('Graph pH', self)
self.pHToGraph.move(10,160)
self.pHToGraph.setToolTip('Show pH in live graph')
self.pHToGraph.clicked.connect(self.displaypHGraph)
self.pHSetpointsButton = QPushButton('Update Setpoints', self)
self.pHSetpointsButton.setGeometry(QtCore.QRect(115, 160, 150, 30))
self.pHSetpointsButton.setToolTip('Edit pH Setpoints')
self.pHSetpointsButton.clicked.connect(self.reactorSetpoints)
self.DOLabel = QLabel('<span style="color:blue"><b>DO:</b></span>',self)
font = self.DOLabel.font()
font.setPointSize(22)
self.DOLabel.setFont(font)
self.DOLabel.setGeometry(QtCore.QRect(10,175,100,100))
self.currentDO = QLabel('<b>' + str(current_DO) + ' mg/L</b>', self)
font = self.currentDO.font()
font.setPointSize(22)
self.currentDO.setFont(font)
self.currentDO.setGeometry(QtCore.QRect(60,175,150,100))
self.DOLowerLabel = QLabel('Lower DO setpoint: ', self)
font = self.DOLowerLabel.font()
font.setPointSize(10)
self.DOLowerLabel.setFont(font)
self.DOLowerLabel.setGeometry(QtCore.QRect(10, 225, 115, 50))
self.DOLowerValue = QLabel('{0:0.2f}'.format(lower_DO) + ' mg/L', self)
font = self.DOLowerValue.font()
font.setPointSize(10)
self.DOLowerValue.setFont(font)
self.DOLowerValue.setGeometry(QtCore.QRect(120, 225, 75, 50))
self.DOToGraph = QPushButton('Graph DO', self)
self.DOToGraph.move(10,260)
self.DOToGraph.setToolTip('Show DO in live graph')
self.DOToGraph.clicked.connect(self.displaypHGraph)
self.tempLabel = QLabel('<span style="color:blue"><b>Temperature:</b></span>',self)
font = self.tempLabel.font()
font.setPointSize(22)
self.tempLabel.setFont(font)
self.tempLabel.setGeometry(QtCore.QRect(10,265,190,100))
self.currentTemp = QLabel('<b>' + str(currentTemp) + '\u2103', self)
font = self.currentTemp.font()
font.setPointSize(22)
self.currentTemp.setFont(font)
self.currentTemp.setGeometry(QtCore.QRect(195,265,150,100))
self.currentStatus = QLabel('<b><u>Other Parameters</u><b>', self)
font = self.currentStatus.font()
font.setPointSize(10)
self.currentStatus.setFont(font)
self.currentStatus.setGeometry(QtCore.QRect(10, 325, 200, 50))
self.currentStatus = QLabel('Current Cycle: ' + '<b>' + currentState + '</b>', self)
font = self.currentStatus.font()
font.setPointSize(10)
self.currentStatus.setFont(font)
self.currentStatus.setGeometry(QtCore.QRect(10, 340, 200, 50))
self.currentCycleTime = QLabel('Current Cycle Time (HH:MM:SS): ' + '<b>' + currentCycTime + '</b>', self)
font = self.currentCycleTime.font()
font.setPointSize(10)
self.currentCycleTime.setFont(font)
self.currentCycleTime.setGeometry(QtCore.QRect(10, 355, 250, 50))
self.remaningCycleTime = QLabel('Remaning Cycle Time (HH:MM:SS): ' + '<b>' + remaningCycTime + '</b>', self)
font = self.remaningCycleTime.font()
font.setPointSize(10)
self.remaningCycleTime.setFont(font)
self.remaningCycleTime.setGeometry(QtCore.QRect(10, 370, 275, 50))
self.show()
# just a dummy graph that I got off a tutorial, it works for what
# i need it to do for now
def displaypHGraph(self):
print("Display pH")
self.m = LinePlot(self, width = 16, height = 9)
self.m.setGeometry(QtCore.QRect(300,40,660,370))
self.m.show()
def displayDOGraph(self):
pass
# was playing with how to update labels here. Just a counter
# that counts up the value from the initial
# this will eventually be replaced with sensor inputs
def updatepH(self):
global current_pH
global lower_pH
global upper_pH
current_pH = current_pH + 0.01
display_pH = '{0:0.2f}'.format(current_pH)
if current_pH < lower_pH:
self.currentpH.setText('<span style="color:red"><b>' + str(display_pH) + '</b></span>')
elif current_pH > upper_pH:
self.currentpH.setText('<span style="color:red"><b>' + str(display_pH) + '</b></span>')
else:
self.currentpH.setText('<span style="color:black"><b>' + str(display_pH) + '<b></span>')
# same thing as with the updatepH function except for DO
def updateDO(self):
global current_DO
global lower_DO
current_DO = current_DO + 0.01
display_DO = '{0:0.2f}'.format(current_DO)
if current_DO < lower_DO:
self.currentDO.setText('<span style = "color:red"><b>' + str(display_DO) + ' mg/L</b></span>')
else:
self.currentDO.setText('<span style = "color:black"><b>' + str(display_DO)+ ' mg/L</b></span>')
# popups the reactorSetpoints window to change the setpoints for
# the reactor. This is where I am haiving troubles, the code
# continues before the user can input new setpoints
def reactorSetpoints(self):
exPopup = setpointsPopup(self)
self.updateSetpoints()
# just have it update the one value for now
def updateSetpoints(self):
self.pHUpperValue.setText(str(upper_pH))
# dummy plot, was learning how to put a matplotlib
# it works for now
class LinePlot(FigureCanvas):
def __init__(self, parent=None, width=16, height=9, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding,QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
self.plot()
def plot(self):
data = [6.89,6.90,6.91,6.92,6.93,6.92,6.96,6.99,7.12,7.14,6.98,6.93,7.01,6.90,7.11,7.21,7.13,6.99]
ax = self.figure.add_subplot(111)
ax.plot(data, 'r-')
ax.set_title('pH')
ax.set_xlabel('Time')
ax.set_ylabel('pH Value')
self.draw()
def main():
app = QApplication(sys.argv)
ex = drawMenuBar()
timer = QTimer()
timer.timeout.connect(ex.updatepH)
timer.timeout.connect(ex.updateDO)
timer.start(1000)
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
so all of this works, except the only way I can get the label to update is to close out of the setpoints popup and reopen it. What is a good way to update it upon exiting of the popup window?
Thanks.

Trouble with passing variables in functions

So I'm making a music player in python but I'm having trouble when passing variables into my function and I get this error message:
TypeError: next() takes exactly 3 arguments (2 given)
I've searched on google for an anwser but their programmes and solutions were to different for me to understand how it works and why it works. Anyway here is my code:
import sys
import os
import pygame
from PyQt4 import QtGui, QtCore
from time import sleep
class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(50, 50, 500, 300)
self.setWindowTitle("Music Player Alpha")
AutoPlay = True
Play = True
SongQueue = []
Song = os.listdir('/home/pi/Desktop/Muziek/' )
Song = sorted(Song)
CurrentSong = 0
pygame.mixer.init()
pygame.mixer.music.load('/home/pi/Desktop/Muziek/' + Song[0])
pygame.mixer.music.play()
self.home()
def home(self):
btnQuit = QtGui.QPushButton("Quit", self)
btnQuit.clicked.connect(self.close)
btnPlay = QtGui.QPushButton("Play", self)
btnPlay.clicked.connect(self.play)
btnPlay.move(100, 100)
btnPause = QtGui.QPushButton("Pause", self)
btnPause.clicked.connect(self.pause)
btnPause.move(200, 100)
btnNext = QtGui.QPushButton("Next", self)
btnNext.clicked.connect(self.next)
btnNext.move(300, 100)
btnPrevious = QtGui.QPushButton("Previous", self)
btnPrevious.clicked.connect(self.previous)
btnPrevious.move(0, 100)
self.show()
def close(self):
print("Closing application")
sys.exit()
def play(self, Play):
pygame.mixer.music.unpause()
Play = True
def pause(self, Play):
pygame.mixer.music.pause()
play = False
def next(self, CurrentSong, Song):
print("1")
CurrentSong = CurrentSong + 1
if CurrentSong > len(Song) + 1:
CurrentSong = 0
pygame.mixer.music.load('/home/pi/Desktop/Muziek/' + Song[CurrentSong])
pygame.mixer.music.play()
else:
pygame.mixer.music.load('/home/pi/Desktop/Muziek/' + Song[CurrentSong])
pygame.mixer.music.play()
def previous(self, CurrentSong, Song):
CurrentSong = CurrentSong - 1
if CurrentSong < 0:
CurrentSong = len(Song) -1
pygame.mixer.music.load('/home/pi/Desktop/Muziek/' + Song[CurrentSong])
pygame.mixer.music.play()
else:
pygame.mixer.music.load('/home/pi/Desktop/Muziek/' + Song[CurrentSong])
pygame.mixer.music.play()
app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())
This is where a call is defined:
btnNext.clicked.connect(self.next)
So when the button is clicked you run self.next(mouse_event) This is the function signature:
def next(self, CurrentSong, Song):
So when a button is clicked you send two parameters: self, from the self.next, and an event which has nothing to do with songs, it has info on the click. You were expecting 3 parameters self,CurrentSong,Song, and not an event - so two mistakes. A workaround is to not accept parameters besides self to next, and save the current song in the class:
def next(self,event):
currentSong = self.currentSong
etc... If you want to forego the event you can lambda hide it:
btnNext.clicked.connect(lambda e:self.next)
and change next accordingly.

Categories