updating qlabel after input waiting - python

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.

Related

Get padding from theme/make native sidebar in PyQt5

I'm trying to make a native looking sidebar that can expand and collapse in PyQt5. I've managed to create this:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtCore import pyqtProperty
from PyQt5.QtGui import *
class Sidebar(QListWidget):
def __init__(self, buttons: list = None):
super().__init__()
font = QFont()
font.setPointSize(12)
self.setFont(font)
self.setIconSize(QSize(35, 35))
for button in buttons:
self.addItem(button)
self.maxWidth = self.sizeHintForColumn(0) + 10
iconWidth = self.iconSize().width()
self.minWidth = iconWidth + 16
self.awidth = self.minWidth
self.expandAnimation = QPropertyAnimation(self, b'awidth')
self.expandAnimation.setEndValue(self.maxWidth)
self.expandAnimation.setDuration(200)
self.expandAnimation.setEasingCurve(QEasingCurve.InOutCubic)
self.contractAnimation = QPropertyAnimation(self, b'awidth')
self.contractAnimation.setEndValue(self.minWidth)
self.contractAnimation.setDuration(200)
self.contractAnimation.setEasingCurve(QEasingCurve.InOutCubic)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.setTextElideMode(Qt.TextElideMode.ElideNone)
def leaveEvent(self, e) -> None:
self.contractAnimation.start()
def enterEvent(self, e) -> None:
self.expandAnimation.start()
#pyqtProperty(int)
def awidth(self) -> int:
return self._awidth
#awidth.setter
def awidth(self, value) -> None:
self._awidth = value
super().setFixedWidth(self._awidth)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.buttonState = False
self.setMinimumSize(500, 300)
button1 = QListWidgetItem(QIcon.fromTheme('battery'), 'Button 1')
button2 = QListWidgetItem(QIcon.fromTheme('computer'), 'Button 2')
button3 = QListWidgetItem(QIcon.fromTheme('camera-web'), 'Button 3')
self.sidebar = Sidebar([button1, button2, button3])
self.sidebar.setSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Expanding)
self.mainWidget = QPushButton()
self.mainWidget.setText('0')
font = QFont()
font.setPointSize(20)
font.setBold(True)
self.mainWidget.setFont(font)
self.mainWidget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
self.mainWidget.pressed.connect(self.buttonPressed)
layout = QHBoxLayout()
layout.addWidget(self.sidebar)
layout.addWidget(self.mainWidget)
centralWidget = QWidget()
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
self.sidebar.itemSelectionChanged.connect(self.sidebarChanged)
def sidebarChanged(self):
selection = self.sidebar.selectedIndexes()[0].row()
print(selection)
self.mainWidget.setText(str(selection))
def buttonPressed(self):
if self.buttonState:
self.sidebar.contractAnimation.start()
else:
self.sidebar.expandAnimation.start()
self.buttonState = not self.buttonState
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
This works well with my theme that I use (WhiteSur on KDE), but I couldn't just use self.iconSize().width() for the minimum width, because it would cut off the icon, I had to use self.iconSize().width() + 16, but this means that when I use another theme, like Breeze, it's too wide, I have to use a number like 10. And also with the Breeze theme, the sidebar itself can be selected and have a blue border around it, which I don't want. Is there a way to get the proper icon size that respects the padding and all that, and also a way to make the sidebar itself not selectable? Or is there a better way to make a native-looking sidebar that I can animate expanding and collapsing?

How to make a QTreeView display more than 10 lines

Using Python 3.7 with pyqt5 on Win10
I am working on getting a QTreeView that uses a QStandardItemModel to display more than 10 lines. I want it to show the maximum number of lines the area can actually handle but it stops short at 10 for some unknown (by me at least) reason.
I have tried numerous solutions (some I have remarked out within the code below along with their apparent results) and there are others that I am not including because they did not compile. As of yet I cannot seem to find a way to get the QTreeView to fill the available space and/or show all the lines it can it just stops at 10 lines. I am including a program that runs and shows the issue simply click "Options" then click "Option 1"
from sys import exit as sysExit
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Line(QFrame):
def __init__(self, parent):
QFrame.__init__(self)
self.setFrameShape(QFrame.HLine)
self.setFrameShadow(QFrame.Sunken)
# Users Widget *************************************************
class Disply1(QFrame):
def __init__(self, parent):
QFrame.__init__(self)
self.setFrameShape(QFrame.StyledPanel)
self.setLineWidth(0.2)
# -------
self.header = QVBoxLayout()
Title = QLabel()
Title.setStyleSheet('font: bold 14px')
Title.setText('Option 1 Configuration Settings')
self.header.addWidget(Title)
self.header.addWidget(Line(self))
# -------
self.TreeVew = QTreeView()
self.TreeVew.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.TreeVew.setAlternatingRowColors(True)
# This adjustment did not fix it
# self.TreeVew.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
# This adjustment made it worse
# self.TreeVew.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
self.model = QStandardItemModel(0, 6)
self.model.setHorizontalHeaderLabels([' ', 'Column1', 'Column2', 'Column3', 'Column4', 'Column5'])
self.model.setHeaderData(5, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
# This adjustment did not fix it
# self.model.setRowCount(20)
self.TreeVew.setModel(self.model)
self.TreeVew.setColumnWidth(0, 1)
self.TreeVew.setColumnHidden(0, True)
self.TreeVew.header().setSectionResizeMode(0, QHeaderView.Fixed)
self.TreeVew.header().setStretchLastSection(False)
self.TreeVew.header().setSectionResizeMode(1, QHeaderView.Stretch)
self.TreeVew.setColumnWidth(2, 100)
self.TreeVew.setColumnWidth(3, 100)
self.TreeVew.setColumnWidth(4, 100)
self.TreeVew.setColumnWidth(5, 70)
# This adjustment did not fix it
# self.TreeVew.resize(self.sizeHint().width(), self.maximumHeight())
ItmRecSet = [
{'Id':'01', 'Column1':'R01-C1', 'Column2':'R01-C2', 'Column3':'R01-C3', 'Column4':'R01-C5', 'Column5':'R01-C5'},
{'Id':'02', 'Column1':'R02-C1', 'Column2':'R02-C2', 'Column3':'R02-C3', 'Column4':'R02-C5', 'Column5':'R02-C5'},
{'Id':'03', 'Column1':'R03-C1', 'Column2':'R03-C2', 'Column3':'R03-C3', 'Column4':'R03-C5', 'Column5':'R03-C5'},
{'Id':'04', 'Column1':'R04-C1', 'Column2':'R04-C2', 'Column3':'R04-C3', 'Column4':'R04-C5', 'Column5':'R04-C5'},
{'Id':'05', 'Column1':'R05-C1', 'Column2':'R05-C2', 'Column3':'R05-C3', 'Column4':'R05-C5', 'Column5':'R05-C5'},
{'Id':'06', 'Column1':'R06-C1', 'Column2':'R06-C2', 'Column3':'R06-C3', 'Column4':'R06-C5', 'Column5':'R06-C5'},
{'Id':'07', 'Column1':'R07-C1', 'Column2':'R07-C2', 'Column3':'R07-C3', 'Column4':'R07-C5', 'Column5':'R07-C5'},
{'Id':'08', 'Column1':'R08-C1', 'Column2':'R08-C2', 'Column3':'R08-C3', 'Column4':'R08-C5', 'Column5':'R08-C5'},
{'Id':'09', 'Column1':'R09-C1', 'Column2':'R09-C2', 'Column3':'R09-C3', 'Column4':'R09-C5', 'Column5':'R09-C5'},
{'Id':'10', 'Column1':'R10-C1', 'Column2':'R10-C2', 'Column3':'R10-C3', 'Column4':'R10-C5', 'Column5':'R10-C5'},
{'Id':'11', 'Column1':'R11-C1', 'Column2':'R11-C2', 'Column3':'R11-C3', 'Column4':'R11-C5', 'Column5':'R11-C5'},
{'Id':'12', 'Column1':'R12-C1', 'Column2':'R12-C2', 'Column3':'R12-C3', 'Column4':'R12-C5', 'Column5':'R12-C5'},
{'Id':'13', 'Column1':'R13-C1', 'Column2':'R13-C2', 'Column3':'R13-C3', 'Column4':'R13-C5', 'Column5':'R13-C5'},
{'Id':'14', 'Column1':'R14-C1', 'Column2':'R14-C2', 'Column3':'R14-C3', 'Column4':'R14-C5', 'Column5':'R14-C5'},
{'Id':'15', 'Column1':'R15-C1', 'Column2':'R15-C2', 'Column3':'R15-C3', 'Column4':'R15-C5', 'Column5':'R15-C5'},
{'Id':'16', 'Column1':'R16-C1', 'Column2':'R16-C2', 'Column3':'R16-C3', 'Column4':'R16-C5', 'Column5':'R16-C5'},
{'Id':'17', 'Column1':'R17-C1', 'Column2':'R17-C2', 'Column3':'R17-C3', 'Column4':'R17-C5', 'Column5':'R17-C5'},
{'Id':'18', 'Column1':'R18-C1', 'Column2':'R18-C2', 'Column3':'R18-C3', 'Column4':'R18-C5', 'Column5':'R18-C5'},
{'Id':'19', 'Column1':'R19-C1', 'Column2':'R19-C2', 'Column3':'R19-C3', 'Column4':'R19-C5', 'Column5':'R19-C5'},
{'Id':'20', 'Column1':'R20-C1', 'Column2':'R20-C2', 'Column3':'R20-C3', 'Column4':'R20-C5', 'Column5':'R20-C5'}
]
self.model.setRowCount(0)
for Item in ItmRecSet:
Itm1 = QStandardItem(Item['Id'])
Itm1.setTextAlignment(Qt.AlignLeft)
Itm1.isEditable = False
Itm2 = QStandardItem(Item['Column1'])
Itm2.setTextAlignment(Qt.AlignLeft)
Itm2.isEditable = False
Itm3 = QStandardItem(Item['Column2'])
Itm3.setTextAlignment(Qt.AlignLeft)
Itm3.isEditable = False
Itm4 = QStandardItem(Item['Column3'])
Itm4.setTextAlignment(Qt.AlignLeft)
Itm4.isEditable = False
Itm5 = QStandardItem(Item['Column4'])
Itm5.setTextAlignment(Qt.AlignLeft)
Itm5.isEditable = False
Itm6 = QStandardItem(Item['Column5'])
Itm6.setTextAlignment(Qt.AlignCenter)
Itm6.isEditable = False
self.model.appendRow([Itm1, Itm2, Itm3, Itm4, Itm5, Itm6])
# Using this GridLayout versus the VerticalBox did not fix it
# self.Cntnr = QGridLayout()
# -------
# self.Cntnr.addLayout(self.header,0,0)
# self.Cntnr.addWidget(self.TreeVew,1,0)
# self.Cntnr.setRowStretch(2,4)
self.Cntnr = QVBoxLayout()
self.Cntnr.addLayout(self.header)
self.Cntnr.addWidget(self.TreeVew)
# If this stretch is not included only the header gets stretched the QTreeView still only shows 10 lines
self.Cntnr.addStretch(1)
# -------
self.setLayout(self.Cntnr)
# Debug Widget *************************************************
class Disply2(QFrame):
def __init__(self, parent):
QFrame.__init__(self)
self.setFrameShape(QFrame.StyledPanel)
self.setLineWidth(0.2)
# -------
self.Cntnr = QVBoxLayout()
self.Cntnr.addWidget(QTextEdit('Option 2 Settings Shown Here'))
self.Cntnr.addStretch(1)
# -------
self.setLayout(self.Cntnr)
class OptionButtons(QToolButton):
# Class OptionButtons ("Text", Icon, Connector) inherits from QToolButton
def __init__(self, Text, Icon, Connector):
QToolButton.__init__(self)
self.setText(Text)
self.setIcon(Icon)
self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.setStyleSheet("font: bold;color: blue;height: 55px;width: 55px;")
self.setIconSize(QSize(32,32))
self.clicked.connect(Connector)
############################## Settings Class ##############################
class OptionSettings(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
line = QFrame()
line.setFrameShape(QFrame.HLine)
line.setFrameShadow(QFrame.Sunken)
# Button Area on Left
# Button 1 *************************************************
self.btnOptn1 = OptionButtons('Option1', QIcon('images/opt1.ico'), self.ShowDisply1)
# Button 2 *************************************************
self.btnOptn2 = OptionButtons('Option2', QIcon('images/opt2.ico'), self.ShowDisply2)
# Vertical Box for Buttons *************************************
self.UpLeft = QVBoxLayout()
self.UpLeft.addWidget(self.btnOptn1)
self.UpLeft.addWidget(self.btnOptn2)
self.UpLeft.addStretch(1)
# Display Area on Right
# Widget Flip Display ******************************************
self.UpRite = QHBoxLayout()
self.Contents = QStackedWidget()
self.Contents.addWidget(QTextEdit('Nothing Selected'))
self.Contents.addWidget(Disply1(self))
self.Contents.addWidget(Disply2(self))
self.Contents.addWidget(QTextEdit('Settings Saved'))
self.Contents.setCurrentIndex(0)
self.UpRite.addWidget(self.Contents)
# Button and Display Area on Top
self.Upper = QHBoxLayout()
self.Upper.addLayout(self.UpLeft)
self.Upper.addLayout(self.UpRite)
# Save and Cancel Area on Bottom
self.btnSave = QPushButton("Save")
self.btnSave.clicked.connect(self.SaveSettings)
self.btnCncl = QPushButton("Cancel")
self.btnCncl.clicked.connect(self.close)
self.Lower = QHBoxLayout()
self.Lower.addStretch(1)
self.Lower.addWidget(self.btnSave)
self.Lower.addWidget(self.btnCncl)
# Entire Options Window Layout
self.OuterBox = QVBoxLayout()
self.OuterBox.addLayout(self.Upper)
self.OuterBox.addLayout(self.Lower)
self.setLayout(self.OuterBox)
self.setWindowTitle('Settings')
#Geometry(Left, Top, Width, Hight)
self.setGeometry(250, 250, 550, 450)
self.setModal(True)
self.exec()
def ShowDisply1(self):
self.Contents.setCurrentIndex(1)
def ShowDisply2(self):
self.Contents.setCurrentIndex(2)
def SaveSettings(self):
self.Contents.setCurrentIndex(3)
class CustomItemModel(QStandardItemModel):
def headerData(self, section, orientation, role):
if role == Qt.ForegroundRole:
brush = QBrush()
brush.setColor(Qt.blue)
brush.setStyle(Qt.SolidPattern)
return brush
elif role == Qt.BackgroundRole:
brush = QBrush()
brush.setColor(Qt.yellow)
brush.setStyle(Qt.SolidPattern)
return brush
elif role == Qt.FontRole:
font = QFont()
font.setBold(True)
font.setPointSize(10)
return font
return super().headerData(section, orientation, role)
class ItemDsplyr(QTreeView):
def __init__(self, CentrPane):
QTreeView.__init__(self, CentrPane)
self.CntrPane = CentrPane
self.setEditTriggers(QTreeView().NoEditTriggers)
self.model = CustomItemModel(0, 3)
self.model.setHorizontalHeaderLabels(['1st Col', '2nd Col', '3rd Col'])
self.model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
self.setModel(self.model)
self.setMinimumWidth(250)
self.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
self.header().setStretchLastSection(False)
self.header().setSectionResizeMode(0, QHeaderView.Stretch)
self.setColumnWidth(1, 75)
self.setColumnWidth(2, 100)
class CenterPanel(QWidget):
def __init__(self, MainWin):
QWidget.__init__(self)
self.MyEditor = QTextEdit('Editorial')
self.ItemDsply = ItemDsplyr(self)
CntrPane = QSplitter(Qt.Horizontal, self)
CntrPane.addWidget(self.MyEditor)
CntrPane.addWidget(self.ItemDsply)
CntrPane.setSizes([50,200])
CntrPane.setCollapsible(0, False)
CntrPane.setCollapsible(1, False)
hbox = QHBoxLayout(self)
hbox.addWidget(CntrPane)
self.setLayout(hbox)
class MenuToolBar(QDockWidget):
def __init__(self, MainWin):
QDockWidget.__init__(self)
self.MainWin = MainWin
self.MainMenu = MainWin.menuBar()
self.WndowMenu = self.MainMenu.addMenu('Windows')
self.OptnAct = QAction('Options', self)
self.OptnAct.setStatusTip('Open the Options Window')
self.OptnAct.triggered.connect(MainWin.ShowOptions)
self.WndowMenu.addAction(self.OptnAct)
self.InitToolBar(MainWin)
def InitToolBar(self, MainWin):
self.mainToolBar = MainWin.addToolBar("Quick Access")
self.mainToolBar.addAction(self.OptnAct)
class UI_MainWindow(QMainWindow):
def __init__(self, MainDesktop):
super(UI_MainWindow, self).__init__(MainDesktop)
self.setWindowTitle('Main Window')
self.MnDskTop = MainDesktop
# Left, Top, Width, Height
self.setGeometry(200, 200, 550, 550)
self.CenterPane = CenterPanel(self)
self.setCentralWidget(self.CenterPane)
self.MenuToolBar = MenuToolBar(self)
def ShowOptions(self):
self.Options = OptionSettings(self)
if __name__ == '__main__':
MainApp = QApplication([])
MainGui = UI_MainWindow(MainApp.desktop())
MainGui.show()
sysExit(MainApp.exec_())
Again what I had expected is that the QTreeView would fill the available space and/or show as many rows as possible within the given space. However, as stated it stops short and only displays just 10 lines maximum.
I removed the line self.Cntnr.addStretch(1), that's what happened:
from sys import exit as sysExit
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Line(QFrame):
def __init__(self, parent):
QFrame.__init__(self)
self.setFrameShape(QFrame.HLine)
self.setFrameShadow(QFrame.Sunken)
# Users Widget *************************************************
class Disply1(QFrame):
def __init__(self, parent):
QFrame.__init__(self)
self.setFrameShape(QFrame.StyledPanel)
self.setLineWidth(0.2)
# -------
self.header = QVBoxLayout()
Title = QLabel()
Title.setStyleSheet('font: bold 14px')
Title.setText('Option 1 Configuration Settings')
self.header.addWidget(Title)
self.header.addWidget(Line(self))
# -------
self.TreeVew = QTreeView()
self.TreeVew.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.TreeVew.setAlternatingRowColors(True)
# This adjustment did not fix it
# self.TreeVew.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
# This adjustment made it worse
# self.TreeVew.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
self.model = QStandardItemModel(0, 6)
self.model.setHorizontalHeaderLabels([' ', 'Column1', 'Column2', 'Column3', 'Column4', 'Column5'])
self.model.setHeaderData(5, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
# This adjustment did not fix it
# self.model.setRowCount(20)
self.TreeVew.setModel(self.model)
self.TreeVew.setColumnWidth(0, 1)
self.TreeVew.setColumnHidden(0, True)
self.TreeVew.header().setSectionResizeMode(0, QHeaderView.Fixed)
self.TreeVew.header().setStretchLastSection(False)
self.TreeVew.header().setSectionResizeMode(1, QHeaderView.Stretch)
self.TreeVew.setColumnWidth(2, 100)
self.TreeVew.setColumnWidth(3, 100)
self.TreeVew.setColumnWidth(4, 100)
self.TreeVew.setColumnWidth(5, 70)
# This adjustment did not fix it
# self.TreeVew.resize(self.sizeHint().width(), self.maximumHeight())
## self.TreeVew.resize(400, 600)
ItmRecSet = [
{'Id':'01', 'Column1':'R01-C1', 'Column2':'R01-C2', 'Column3':'R01-C3', 'Column4':'R01-C5', 'Column5':'R01-C5'},
{'Id':'02', 'Column1':'R02-C1', 'Column2':'R02-C2', 'Column3':'R02-C3', 'Column4':'R02-C5', 'Column5':'R02-C5'},
{'Id':'03', 'Column1':'R03-C1', 'Column2':'R03-C2', 'Column3':'R03-C3', 'Column4':'R03-C5', 'Column5':'R03-C5'},
{'Id':'04', 'Column1':'R04-C1', 'Column2':'R04-C2', 'Column3':'R04-C3', 'Column4':'R04-C5', 'Column5':'R04-C5'},
{'Id':'05', 'Column1':'R05-C1', 'Column2':'R05-C2', 'Column3':'R05-C3', 'Column4':'R05-C5', 'Column5':'R05-C5'},
{'Id':'06', 'Column1':'R06-C1', 'Column2':'R06-C2', 'Column3':'R06-C3', 'Column4':'R06-C5', 'Column5':'R06-C5'},
{'Id':'07', 'Column1':'R07-C1', 'Column2':'R07-C2', 'Column3':'R07-C3', 'Column4':'R07-C5', 'Column5':'R07-C5'},
{'Id':'08', 'Column1':'R08-C1', 'Column2':'R08-C2', 'Column3':'R08-C3', 'Column4':'R08-C5', 'Column5':'R08-C5'},
{'Id':'09', 'Column1':'R09-C1', 'Column2':'R09-C2', 'Column3':'R09-C3', 'Column4':'R09-C5', 'Column5':'R09-C5'},
{'Id':'10', 'Column1':'R10-C1', 'Column2':'R10-C2', 'Column3':'R10-C3', 'Column4':'R10-C5', 'Column5':'R10-C5'},
{'Id':'11', 'Column1':'R11-C1', 'Column2':'R11-C2', 'Column3':'R11-C3', 'Column4':'R11-C5', 'Column5':'R11-C5'},
{'Id':'12', 'Column1':'R12-C1', 'Column2':'R12-C2', 'Column3':'R12-C3', 'Column4':'R12-C5', 'Column5':'R12-C5'},
{'Id':'13', 'Column1':'R13-C1', 'Column2':'R13-C2', 'Column3':'R13-C3', 'Column4':'R13-C5', 'Column5':'R13-C5'},
{'Id':'14', 'Column1':'R14-C1', 'Column2':'R14-C2', 'Column3':'R14-C3', 'Column4':'R14-C5', 'Column5':'R14-C5'},
{'Id':'15', 'Column1':'R15-C1', 'Column2':'R15-C2', 'Column3':'R15-C3', 'Column4':'R15-C5', 'Column5':'R15-C5'},
{'Id':'16', 'Column1':'R16-C1', 'Column2':'R16-C2', 'Column3':'R16-C3', 'Column4':'R16-C5', 'Column5':'R16-C5'},
{'Id':'17', 'Column1':'R17-C1', 'Column2':'R17-C2', 'Column3':'R17-C3', 'Column4':'R17-C5', 'Column5':'R17-C5'},
{'Id':'18', 'Column1':'R18-C1', 'Column2':'R18-C2', 'Column3':'R18-C3', 'Column4':'R18-C5', 'Column5':'R18-C5'},
{'Id':'19', 'Column1':'R19-C1', 'Column2':'R19-C2', 'Column3':'R19-C3', 'Column4':'R19-C5', 'Column5':'R19-C5'},
{'Id':'20', 'Column1':'R20-C1', 'Column2':'R20-C2', 'Column3':'R20-C3', 'Column4':'R20-C5', 'Column5':'R20-C5'}
]
self.model.setRowCount(0)
for Item in ItmRecSet:
Itm1 = QStandardItem(Item['Id'])
Itm1.setTextAlignment(Qt.AlignLeft)
Itm1.isEditable = False
Itm2 = QStandardItem(Item['Column1'])
Itm2.setTextAlignment(Qt.AlignLeft)
Itm2.isEditable = False
Itm3 = QStandardItem(Item['Column2'])
Itm3.setTextAlignment(Qt.AlignLeft)
Itm3.isEditable = False
Itm4 = QStandardItem(Item['Column3'])
Itm4.setTextAlignment(Qt.AlignLeft)
Itm4.isEditable = False
Itm5 = QStandardItem(Item['Column4'])
Itm5.setTextAlignment(Qt.AlignLeft)
Itm5.isEditable = False
Itm6 = QStandardItem(Item['Column5'])
Itm6.setTextAlignment(Qt.AlignCenter)
Itm6.isEditable = False
self.model.appendRow([Itm1, Itm2, Itm3, Itm4, Itm5, Itm6])
# Using this GridLayout versus the VerticalBox did not fix it
# self.Cntnr = QGridLayout()
# -------
# self.Cntnr.addLayout(self.header,0,0)
# self.Cntnr.addWidget(self.TreeVew,1,0)
# self.Cntnr.setRowStretch(2,4)
self.Cntnr = QVBoxLayout()
self.Cntnr.addLayout(self.header)
self.Cntnr.addWidget(self.TreeVew)
# If this stretch is not included only the header gets stretched the QTreeView still only shows 10 lines
#--- self.Cntnr.addStretch(1) # <<<=======
# -------
self.setLayout(self.Cntnr)
# Debug Widget *************************************************
class Disply2(QFrame):
def __init__(self, parent):
QFrame.__init__(self)
self.setFrameShape(QFrame.StyledPanel)
self.setLineWidth(0.2)
# -------
self.Cntnr = QVBoxLayout()
self.Cntnr.addWidget(QTextEdit('Option 2 Settings Shown Here'))
self.Cntnr.addStretch(1)
# -------
self.setLayout(self.Cntnr)
class OptionButtons(QToolButton):
# Class OptionButtons ("Text", Icon, Connector) inherits from QToolButton
def __init__(self, Text, Icon, Connector):
QToolButton.__init__(self)
self.setText(Text)
self.setIcon(Icon)
self.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
self.setStyleSheet("font: bold;color: blue;height: 55px;width: 55px;")
self.setIconSize(QSize(32,32))
self.clicked.connect(Connector)
############################## Settings Class ##############################
class OptionSettings(QDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
line = QFrame()
line.setFrameShape(QFrame.HLine)
line.setFrameShadow(QFrame.Sunken)
# Button Area on Left
# Button 1 *************************************************
self.btnOptn1 = OptionButtons('Option1', QIcon('Ok.png'), self.ShowDisply1)
# Button 2 *************************************************
self.btnOptn2 = OptionButtons('Option2', QIcon('images/opt2.ico'), self.ShowDisply2)
# Vertical Box for Buttons *************************************
self.UpLeft = QVBoxLayout()
self.UpLeft.addWidget(self.btnOptn1)
self.UpLeft.addWidget(self.btnOptn2)
self.UpLeft.addStretch(1)
# Display Area on Right
# Widget Flip Display ******************************************
self.UpRite = QHBoxLayout()
self.Contents = QStackedWidget()
self.Contents.addWidget(QTextEdit('Nothing Selected'))
self.Contents.addWidget(Disply1(self))
self.Contents.addWidget(Disply2(self))
self.Contents.addWidget(QTextEdit('Settings Saved'))
self.Contents.setCurrentIndex(0)
self.UpRite.addWidget(self.Contents)
# Button and Display Area on Top
self.Upper = QHBoxLayout()
self.Upper.addLayout(self.UpLeft)
self.Upper.addLayout(self.UpRite)
# Save and Cancel Area on Bottom
self.btnSave = QPushButton("Save")
self.btnSave.clicked.connect(self.SaveSettings)
self.btnCncl = QPushButton("Cancel")
self.btnCncl.clicked.connect(self.close)
self.Lower = QHBoxLayout()
self.Lower.addStretch(1)
self.Lower.addWidget(self.btnSave)
self.Lower.addWidget(self.btnCncl)
# Entire Options Window Layout
self.OuterBox = QVBoxLayout()
self.OuterBox.addLayout(self.Upper)
self.OuterBox.addLayout(self.Lower)
self.setLayout(self.OuterBox)
self.setWindowTitle('Settings')
#Geometry(Left, Top, Width, Hight)
self.setGeometry(250, 250, 550, 450)
self.setModal(True)
self.exec()
def ShowDisply1(self):
self.Contents.setCurrentIndex(1)
def ShowDisply2(self):
self.Contents.setCurrentIndex(2)
def SaveSettings(self):
self.Contents.setCurrentIndex(3)
class CustomItemModel(QStandardItemModel):
def headerData(self, section, orientation, role):
if role == Qt.ForegroundRole:
brush = QBrush()
brush.setColor(Qt.blue)
brush.setStyle(Qt.SolidPattern)
return brush
elif role == Qt.BackgroundRole:
brush = QBrush()
brush.setColor(Qt.yellow)
brush.setStyle(Qt.SolidPattern)
return brush
elif role == Qt.FontRole:
font = QFont()
font.setBold(True)
font.setPointSize(10)
return font
return super().headerData(section, orientation, role)
class ItemDsplyr(QTreeView):
def __init__(self, CentrPane):
QTreeView.__init__(self, CentrPane)
self.CntrPane = CentrPane
self.setEditTriggers(QTreeView().NoEditTriggers)
self.model = CustomItemModel(0, 3)
self.model.setHorizontalHeaderLabels(['1st Col', '2nd Col', '3rd Col'])
self.model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
self.setModel(self.model)
self.setMinimumWidth(250)
self.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
self.header().setStretchLastSection(False)
self.header().setSectionResizeMode(0, QHeaderView.Stretch)
self.setColumnWidth(1, 75)
self.setColumnWidth(2, 100)
class CenterPanel(QWidget):
def __init__(self, MainWin):
QWidget.__init__(self)
self.MyEditor = QTextEdit('Editorial')
self.ItemDsply = ItemDsplyr(self)
CntrPane = QSplitter(Qt.Horizontal, self)
CntrPane.addWidget(self.MyEditor)
CntrPane.addWidget(self.ItemDsply)
CntrPane.setSizes([50,200])
CntrPane.setCollapsible(0, False)
CntrPane.setCollapsible(1, False)
hbox = QHBoxLayout(self)
hbox.addWidget(CntrPane)
self.setLayout(hbox)
class MenuToolBar(QDockWidget):
def __init__(self, MainWin):
QDockWidget.__init__(self)
self.MainWin = MainWin
self.MainMenu = MainWin.menuBar()
self.WndowMenu = self.MainMenu.addMenu('Windows')
self.OptnAct = QAction('Options', self)
self.OptnAct.setStatusTip('Open the Options Window')
self.OptnAct.triggered.connect(MainWin.ShowOptions)
self.WndowMenu.addAction(self.OptnAct)
self.InitToolBar(MainWin)
def InitToolBar(self, MainWin):
self.mainToolBar = MainWin.addToolBar("Quick Access")
self.mainToolBar.addAction(self.OptnAct)
class UI_MainWindow(QMainWindow):
def __init__(self, MainDesktop):
super(UI_MainWindow, self).__init__(MainDesktop)
self.setWindowTitle('Main Window')
self.MnDskTop = MainDesktop
# Left, Top, Width, Height
self.setGeometry(200, 200, 550, 550)
self.CenterPane = CenterPanel(self)
self.setCentralWidget(self.CenterPane)
self.MenuToolBar = MenuToolBar(self)
def ShowOptions(self):
self.Options = OptionSettings(self)
if __name__ == '__main__':
MainApp = QApplication([])
MainGui = UI_MainWindow(MainApp.desktop())
MainGui.show()
sysExit(MainApp.exec_())

Position internal widget inside QStackedWidget object

I have several tabs and inside the "admin" tab I want to display two pages: one locked page (before entering credentials) and another unlocked page (after successful login). To do this, I'm using a QStackedWidget() to switch between the two pages. I have created a locked login screen but can't seem to move the object to the center of the page.
I have looked at moving widgets inside QStackedWidget and centering widgets in the center of the screen but my objects do not seem to change position. I've tried to move the entire internal widget using move() to the center of the screen using the desktop dimension and the parent widget to no avail. How would I be able to move the login fields to the center of the page? Thanks!
Current:
Desired:
Code:
from PyQt4 import QtGui, QtCore
# from load_CSS import load_CSS
# from widgets import UniversalPlotWidget
import sys
import time
def exit_application():
"""Exit program event handler"""
sys.exit(1)
class VerticalTabBar(QtGui.QTabBar):
def __init__(self, width, height, parent=None):
super(VerticalTabBar, self).__init__(parent)
self.width = width
self.height = height
def tabSizeHint(self, index):
return QtCore.QSize(self.width, self.height)
def paintEvent(self, event):
painter = QtGui.QStylePainter(self)
tab_options = QtGui.QStyleOptionTab()
for tab in range(self.count()):
self.initStyleOption(tab_options, tab)
painter.drawControl(QtGui.QStyle.CE_TabBarTabShape, tab_options)
painter.save()
size = tab_options.rect.size()
size.transpose()
rectangle = QtCore.QRect(QtCore.QPoint(), size)
rectangle.moveCenter(tab_options.rect.center())
tab_options.rect = rectangle
center = self.tabRect(tab).center()
painter.translate(center)
painter.rotate(90)
painter.translate(-center)
painter.drawControl(QtGui.QStyle.CE_TabBarTabLabel, tab_options);
painter.restore()
class TabWidget(QtGui.QTabWidget):
def __init__(self, *args, **kwargs):
QtGui.QTabWidget.__init__(self, *args, **kwargs)
self.setTabBar(VerticalTabBar(kwargs.pop('width'), kwargs.pop('height')))
self.setTabPosition(QtGui.QTabWidget.West)
self.setTabShape(QtGui.QTabWidget.Rounded)
class AdminTabWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(AdminTabWidget, self).__init__(parent)
self.setWindowModality(QtCore.Qt.ApplicationModal)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.admin_page_locked_init()
self.admin_page_unlocked_init()
self.admin_page_layout = QtGui.QGridLayout()
self.admin_page_switch = QtGui.QStackedWidget()
self.admin_page_switch.addWidget(self.admin_locked_tab)
self.admin_page_switch.addWidget(self.admin_unlocked_tab)
self.admin_page_switch.setCurrentIndex(0)
self.admin_page_layout.addWidget(self.admin_page_switch,0,0)
def admin_page_locked_init(self):
self.admin_locked_tab = QtGui.QWidget()
self.admin_locked_tab.setFixedSize(550,225)
self.admin_locked_layout = QtGui.QGridLayout()
self.username_label = QtGui.QLabel('Username: ')
self.username_field = QtGui.QLineEdit()
self.username_field.returnPressed.connect(self.verify_credentials)
self.space_label = QtGui.QLabel(' ')
self.space_label.setFixedHeight(25)
self.password_label = QtGui.QLabel('Password: ')
self.password_field = QtGui.QLineEdit()
self.password_field.returnPressed.connect(self.verify_credentials)
self.password_field.setEchoMode(QtGui.QLineEdit.Password)
self.verify_button = QtGui.QPushButton('Ok')
self.verify_button.clicked.connect(self.verify_credentials)
self.cancel_button = QtGui.QPushButton('Cancel')
self.cancel_button.clicked.connect(self.unauthorized)
self.status_label = QtGui.QLabel('')
self.status_label.setAlignment(QtCore.Qt.AlignCenter)
self.button_layout = QtGui.QGridLayout()
self.button_layout.addWidget(self.verify_button,0,0,1,1)
self.button_layout.addWidget(self.cancel_button,0,1,1,1)
self.admin_locked_layout.addWidget(self.username_label,0,0,1,1)
self.admin_locked_layout.addWidget(self.username_field,0,1,1,1)
self.admin_locked_layout.addWidget(self.space_label,1,0,1,3)
self.admin_locked_layout.addWidget(self.password_label,2,0,1,1)
self.admin_locked_layout.addWidget(self.password_field,2,1,1,1)
self.admin_locked_layout.addWidget(self.status_label,3,0,1,3)
self.admin_locked_layout.addLayout(self.button_layout,4,0,1,3)
self.admin_locked_tab.setLayout(self.admin_locked_layout)
def verify_credentials(self):
print('button pressed')
# Grab username/password from input fields
self.username = str(self.username_field.text())
self.password = str(self.password_field.text())
self.status_label.setText('Verifying')
self.status_label.setStyleSheet('QLabel {color: rgb(117,255,161)}')
self.spin(.001)
print('verified')
def spin(self, seconds):
"""Pause for set amount of seconds, replaces time.sleep so program doesnt stall"""
time_end = time.time() + seconds
while time.time() < time_end:
QtGui.QApplication.processEvents()
def unauthorized(self):
print('unauthorized')
self.status_label.setText('Invalid username and/or password')
self.status_label.setStyleSheet('QLabel {color: rgb(255,65,106)}')
def admin_page_unlocked_init(self):
self.admin_unlocked_tab = QtGui.QWidget()
admin_unlocked_layout = QtGui.QGridLayout()
admin_unlocked_button = QtGui.QPushButton('unlocked')
admin_unlocked_layout.addWidget(admin_unlocked_button)
self.admin_unlocked_tab.setLayout(admin_unlocked_layout)
def get_admin_page_layout(self):
return self.admin_page_layout
if __name__ == '__main__':
# Create main application window
app = QtGui.QApplication(sys.argv)
# app.setStyleSheet(load_CSS(1))
app.setStyle(QtGui.QStyleFactory.create("Cleanlooks"))
font = QtGui.QFont('Ubuntu', 20)
font.setWeight(70)
app.setFont(font)
screen_height = QtGui.QApplication.desktop().screenGeometry().height()
main_window_tab = TabWidget(width=300, height=screen_height/8)
main_window_tab.setWindowTitle("Tab Layout")
main_window_tab.setWindowFlags(QtCore.Qt.FramelessWindowHint)
main_window_tab.showMaximized()
tab1 = QtGui.QWidget()
tab2 = QtGui.QWidget()
tab3 = QtGui.QWidget()
tab4 = QtGui.QWidget()
tab5 = QtGui.QWidget()
tab6 = QtGui.QWidget()
tab7 = QtGui.QWidget()
admin_tab = QtGui.QWidget()
admin_tab_widget = AdminTabWidget()
admin_tab.setLayout(admin_tab_widget.get_admin_page_layout())
main_window_tab.addTab(admin_tab, "Admin")
main_window_tab.addTab(tab1, "tab1")
main_window_tab.addTab(tab2, "tab2")
main_window_tab.addTab(tab3, "tab3")
main_window_tab.addTab(tab4, "tab4")
main_window_tab.addTab(tab5, "tab5")
main_window_tab.addTab(tab6, "tab6")
main_window_tab.addTab(tab7, "tab7")
main_window_tab.show()
QtGui.QShortcut(QtGui.QKeySequence('Ctrl+Q'), main_window_tab, exit_application)
sys.exit(app.exec_())
The idea is to set the QStackedWidget with the Qt::AlignCenter alignment in the layout so it changes:
self.admin_page_layout.addWidget(self.admin_page_switch, 0, 0)
to:
self.admin_page_layout.addWidget(self.admin_page_switch, 0, 0, alignment=QtCore.Qt.AlignCenter)

How to have dynamic fields in PyQt5?

I have a piece of PyQt5 code like this:
def displayDefaultParameters(self):
#Create Default Parameters
self.useDFParamsLabel = QLabel(self)
self.useDFParamsLabel.setText('Default Parameters:')
self.useDFParamsLabelFont = QFont("Calibri", 15)
self.useDFParamsLabelFont.setUnderline(True)
self.useDFParamsLabel.setFont(self.useDFParamsLabelFont)
self.useDFParamsLabel.setGeometry(QRect(650, 75, 220, 50))
self.useDFParamsLabel.show()
self.DFParamsQLabel = QLabel(self)
pixmap = QPixmap('question1.png')
self.DFParamsQLabel.setPixmap(pixmap)
self.DFParamsQLabel.setToolTip('Default Parameters when \nno input is provided.')
self.DFParamsQLabel.move(860,85)
#FIELDS THAT WILL BE CHANGED DYNAMICALLY
self.paramFont = QFont("Arial", 12, QFont.Bold)
self.DLabel = QLabel(self)
self.DLabel.setText('D = ' + str(self.D))
self.DLabel.setFont(self.paramFont)
self.DLabel.setGeometry(QRect(675, 110, 220, 50))
self.DLabel.show()
self.RoNLabel = QLabel(self)
self.RoNLabel.setText('R_on = ' + str(self.R_on) + ' \u03A9')
self.RoNLabel.setFont(self.paramFont)
self.RoNLabel.setGeometry(QRect(675, 135, 220, 50))
self.RoNLabel.show()
self.RoFFLabel = QLabel(self)
self.RoFFLabel.setText('R_off = ' + str(self.R_off) + ' \u03A9')
self.RoFFLabel.setFont(self.paramFont)
self.RoFFLabel.setGeometry(QRect(675, 160, 220, 50))
self.RoFFLabel.show()
As you can see self.D, self.R_on and self.R_off are class variables. Now I have initialized these class variables with some value, but it can be also user input. After the user inputs the value I need to be able to change the values. As for how the class values will be input by the user is through a form which looks like the form on this question. After clicking 'OK' the new values should be reflected.
So far whatever I have tried it is overwriting on previous values. How can we implement this?
You have to use the signals to notify changes to the other parts of the application, in this case create a model that every time a property is changed it will be notified through signals, that signals will be connected to a slot, and in that slot it will modify the GUI.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Model(QtCore.QObject):
D_Changed = QtCore.pyqtSignal(float)
R_on_Changed = QtCore.pyqtSignal(float)
R_off_Changed = QtCore.pyqtSignal(float)
W_0_Changed = QtCore.pyqtSignal(float)
def __init__(self, parent=None):
super(Model, self).__init__(parent)
self._d = 0.0
self._r_on = 0.0
self._r_off = 0.0
self._w_0 = 0.0
def D(self):
return self._d
def setD(self, d):
if self._d == d: return
self._d = d
self.D_Changed.emit(d)
def R_on(self):
return self._r_on
def setR_on(self, r_on):
if self._r_on == r_on: return
self._r_on = r_on
self.R_on_Changed.emit(r_on)
def R_off(self):
return self._r_off
def setR_off(self, r_off):
if self._r_off == r_off: return
self._r_off = r_off
self.R_off_Changed.emit(r_off)
D = QtCore.pyqtProperty(float, fget=D, fset=setD, notify=D_Changed)
R_on = QtCore.pyqtProperty(float, fget=R_on, fset=setR_on, notify=R_on_Changed)
R_off = QtCore.pyqtProperty(float, fget=R_off, fset=setR_off, notify=R_off_Changed)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
model = Model(self)
self.d_label = QtWidgets.QLabel()
self.r_on_label = QtWidgets.QLabel()
self.r_off_label = QtWidgets.QLabel()
model.D_Changed.connect(self.on_D_Changed)
model.R_on_Changed.connect(self.on_R_on_Changed)
model.R_off_Changed.connect(self.on_R_off_Changed)
model.setD(10.0)
model.setR_on(100)
model.setR_off(16000)
d_le = QtWidgets.QDoubleSpinBox(
maximum=sys.float_info.max,
value=model.D,
valueChanged=model.setD
)
r_on_le = QtWidgets.QDoubleSpinBox(
maximum=sys.float_info.max,
value=model.R_on,
valueChanged=model.setR_on
)
r_off_le = QtWidgets.QDoubleSpinBox(
maximum=sys.float_info.max,
value=model.R_off,
valueChanged=model.setR_off
)
groub_box_input = QtWidgets.QGroupBox("Edit Values")
flay = QtWidgets.QFormLayout()
flay.addRow("D (nm)", d_le)
flay.addRow("R_on (\u03A9)", r_on_le)
flay.addRow("R_off (\u03A9)", r_off_le)
groub_box_input.setLayout(flay)
groub_box_output = QtWidgets.QGroupBox("Default Parameters:")
vlay = QtWidgets.QVBoxLayout()
vlay.addWidget(self.d_label)
vlay.addWidget(self.r_on_label)
vlay.addWidget(self.r_off_label)
groub_box_output.setLayout(vlay)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(groub_box_input)
lay.addWidget(groub_box_output)
#QtCore.pyqtSlot(float)
def on_D_Changed(self, d):
self.d_label.setText('D = {}'.format(d))
#QtCore.pyqtSlot(float)
def on_R_on_Changed(self, r_on):
self.r_on_label.setText('R_on = {}\u03A9'.format(r_on))
#QtCore.pyqtSlot(float)
def on_R_off_Changed(self, r_off):
self.r_off_label.setText('R_off = {}\u03A9'.format(r_off))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setStyle("fusion")
w = Widget()
w.show()
sys.exit(app.exec_())

calculate two value in PyQt

I`m playing with PyQt, and trying to add two values (numbers) together.
When I try do display the output for this, I just get this message:
Picture here
my code:
labelwidth = QLabel('Width in meter', self)
self.width = QLineEdit(self)
self.width.move (100,0)
labelwidth.move (5,0)
labeldepth = QLabel('Depth in meter', self)
self.depth = QLineEdit(self)
self.depth.move (100,50)
labeldepth.move (5,50)
#Send data
btn = QPushButton('Send', self)
btn.clicked.connect(self.send_data)
btn.move (100, 100)
self.show()
def send_data(self):
width_to_str = str(self.width)
dept_to_str = str(self.depth)
kvm = width_to_int + dept_to_int
labelkvm = QLabel(kvm, self)
labelkvm.move = (200, 100)
QMessageBox.about(self, "Sendt", kvm)
self.show()
I have tried to convert it to int before it summarize the number.
How can I solve this?
Try it:
import sys
import pandas as pd
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class MainWindow(QWidget):
def __init__(self):
super().__init__()
labelwidth = QLabel('Width in meter', self)
self.width = QLineEdit(self)
self.width.move (100,0)
labelwidth.move (5,0)
labeldepth = QLabel('Depth in meter', self)
self.depth = QLineEdit(self)
self.depth.move (100,50)
labeldepth.move (5,50)
#Send data
btn = QPushButton('Send', self)
btn.clicked.connect(self.send_data)
btn.move (100, 100)
self.show()
def send_data(self):
width_to_str = int(self.width.text()) # <---
dept_to_str = int(self.depth.text()) # <---
kvm = str(width_to_str + dept_to_str) # <---
labelkvm = QLabel(kvm, self)
labelkvm.move = (200, 100)
QMessageBox.about(self, "Sendt", kvm)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
sys.exit(app.exec_())

Categories