good day, I wonder if someone could tell me why I end up with the following lines around the edge of my GUI.
The skeleton code is below which replicates the problem. I've tried adding stylesheets and QT alignment but to no avail. I think the issue could be with the QScrollArea(). I would love any help as this one has me stumped. Thank you
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.main_window()
def main_window(self):
self.setGeometry(0, 0, 500, 500)
self.grid = QGridLayout()
vbox = QVBoxLayout()
wrapper_widget = QWidget()
wrapper_widget.setLayout(self.grid)
# Bars
scroll = QScrollArea()
scroll.setWidget(wrapper_widget)
master_widget = QWidget()
vbox.addWidget(scroll)
master_widget.setLayout(vbox)
self.setCentralWidget(master_widget)
# Show
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec())
Related
I'm new at PyQt, and I'm trying to create a main window containing two custom widgets, the first being a data grapher, the second being a QGridLayout containing QLabels. Problem is: the two widgets open in separate windows and have no content.
I've found multiple posts with a similar problem:
PyQt5 Custom Widget Opens in Another Window
Custom widget does not appear on Main Window
PyQt5 Custom Widget Opens in Another Window
And even a FAQ on this specific problem: https://www.pythonguis.com/faq/pyqt-widgets-appearing-as-separate-windows/
But I haven't been able to figure out why my code doesn't work. My aim is to obtain a result as shown below on the left, but instead I'm getting a result as shown on the right:
My code is the following (can be copied and run as it is):
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget, QGridLayout
from PyQt5.QtGui import QFont
import sys
import pyqtgraph as pg
class CustomWidget_1(QWidget):
def __init__(self):
super(CustomWidget_1, self).__init__()
self.channels = [1, 2, 3, 4, 5, 6, 7, 8]
self.win = pg.GraphicsLayoutWidget(title='Plot', size=(800, 600))
self.plots = list()
self.curves = list()
for i in range(len(self.channels)):
p = self.win.addPlot(row=i, col=0)
p.showAxis('left', False)
p.setMenuEnabled('left', False)
p.showAxis('bottom', False)
p.setMenuEnabled('bottom', False)
self.plots.append(p)
curve = p.plot()
self.curves.append(curve)
self.win.show()
print('CustomWidget_1 initialized.')
class CustomWidget_2(QWidget):
def __init__(self, labelnames):
super(CustomWidget_2, self).__init__()
self.grid = QGridLayout()
self.labelnames = labelnames
self.qlabels = []
for label in self.labelnames:
labelBox = QLabel(label)
labelBox.setFont(QFont('Arial', 16))
labelBox.setStyleSheet('border: 2px solid black;')
labelBox.setAlignment(Qt.AlignCenter)
self.qlabels.append(labelBox)
index = self.labelnames.index(label)
q, r = divmod(index, 6)
self.grid.addWidget(labelBox, q, r)
print('CustomWidget_2 initialized.')
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.labelnames = ['label 1', 'label 2', 'label 3']
self.CustomWidget_1 = CustomWidget_1()
self.CustomWidget_1.setParent(self)
self.CustomWidget_1.show()
self.CustomWidget_2 = CustomWidget_2(self.labelnames)
self.CustomWidget_2.setParent(self)
self.CustomWidget_2.show()
self.mainLayout = QVBoxLayout()
self.mainLayout.addWidget(self.CustomWidget_1)
self.mainLayout.addWidget(self.CustomWidget_2)
self.setLayout(self.mainLayout)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
predictVisualizer = MainWindow()
sys.exit(app.exec())
Could anyone tell me what I'm doing wrong and how I could fix it? Any pointers towards tutorials and/or templates would be greatly appreciated as well! Thanks!
you should write fewer lines of code and debug slowly, if you are new to pyqt5 you should read carefully the basic Layout creation, like you are creating a website interface, link: https://www.pythonguis.com/tutorials/pyqt-layouts/
This is the code I have edited, you can can refer:
import sys
from PyQt5.QtCore import QSize,Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget,QGridLayout,QVBoxLayout,QLabel,QHBoxLayout
from PyQt5.QtGui import QPalette, QColor
class CustomWidget_1(QWidget):
def __init__(self,color):
super(CustomWidget_1, self).__init__()
self.setAutoFillBackground(True)
layout = QGridLayout()
self.setLayout(layout)
self.setFixedSize(QSize(400,300))
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
class CustomWidget_2(QWidget):
def __init__(self,color):
super(CustomWidget_2, self).__init__()
self.setAutoFillBackground(True)
layout = QHBoxLayout()
self.setLayout(layout)
self.setFixedSize(QSize(400,134))
layout.setContentsMargins(70,0,0,0)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
Label1 = QLabel()
Label1.setText('abc')
Label2 = QLabel()
Label2.setText('sad')
Label3 = QLabel()
Label3.setText('qv')
layout.addWidget(Label1)
layout.addWidget(Label2)
layout.addWidget(Label3)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("My App")
layout = QVBoxLayout()
layout.addWidget(CustomWidget_1("blue"))
layout.addWidget(CustomWidget_2("red"))
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
I'm using the QPushButton to load the UI. First -> Jumin -> Department -> next -> next I want to create the UI in order. The problem is that I can not load the third Department into the QMainwindow window. I do not know why
When you create a widget in QVBoxLayout, it changes the size of the widget according to the wallpaper like wxpython layout (wx.all). Can not change the position (move) and size (resize) by automatic centering?
import sys
from PyQt5.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.center_widget = QWidget()
self.setCentralWidget(self.center_widget)
self.FirstUI()
def FirstUI(self):
self.btn1 = QPushButton('test1', self)
self.btn1.move(50, 50)
self.btn1.clicked.connect(self.btn1_click)
def JuminUI(self):
self.ju1 = QLineEdit('13')
self.btn2 = QPushButton('^^^^^^^^^^')
self.ju_text = QLabel('asd')
self.jumim_layout = QVBoxLayout()
self.jumim_layout.addWidget(self.ju_text)
self.jumim_layout.addWidget(self.ju1)
self.jumim_layout.addWidget(self.btn2)
self.centralWidget().setLayout(self.jumim_layout)
self.btn2.clicked.connect(self.btn2_click)
def DepartmentUI(self):
self.depart_layout = QVBoxLayout()
self.depart_layout.addWidget(QPushButton('sdfsdf'))
self.centralWidget().setLayout(self.depart_layout)
def btn1_click(self):
self.btn1.deleteLater()
self.JuminUI()
def btn2_click(self):
self.ju1.deleteLater()
self.btn2.deleteLater()
self.ju_text.deleteLater()
self.DepartmentUI()
if __name__ == "__main__":
app = QApplication(sys.argv)
fream = MainWindow()
fream.show()
app.exec_()
creating and removing widgets is almost always a bad idea, and your code falls into those bad ideas, it's always best to hide the widgets and for that you should use the QStackedWidget, what QStackedWidget does is just make a widget visible on all widgets that you have been assigned by changing the currentIndex.
import sys
from functools import partial
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.center_widget = QtWidgets.QStackedWidget()
self.setCentralWidget(self.center_widget)
self.FirstUI()
self.JuminUI()
self.DepartmentUI()
def FirstUI(self):
widget = QtWidgets.QWidget()
self.btn1 = QtWidgets.QPushButton('test1', widget)
self.btn1.move(50, 50)
self.center_widget.addWidget(widget)
self.btn1.clicked.connect(partial(self.center_widget.setCurrentIndex, 1))
def JuminUI(self):
widget = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(widget)
self.ju1 = QtWidgets.QLineEdit('13')
self.btn2 = QtWidgets.QPushButton('^^^^^^^^^^')
self.ju_text = QtWidgets.QLabel('asd')
lay.addWidget(self.ju_text)
lay.addWidget(self.ju1)
lay.addWidget(self.btn2)
self.center_widget.addWidget(widget)
self.btn2.clicked.connect(partial(self.center_widget.setCurrentIndex, 2))
def DepartmentUI(self):
widget = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(widget)
lay.addWidget(QtWidgets.QPushButton('sdfsdf'))
self.center_widget.addWidget(widget)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
fream = MainWindow()
fream.show()
sys.exit(app.exec_())
I have the following window with frames.
I want frame to be highlighted (in my case change its shape) when mouse is in its area.
from PyQt4 import QtGui, QtCore
import sys
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window_layout = QtGui.QVBoxLayout()
window.setLayout(window_layout)
#fill content
for i in range(10):
label = QtGui.QLabel(str(i))
frame = QtGui.QFrame()
frame_layout = QtGui.QVBoxLayout()
frame.setLayout(frame_layout)
frame_layout.addWidget(label)
window_layout.addWidget(frame)
def layout_widgets(layout):
return (layout.itemAt(i) for i in range(layout.count()))
def mouse_enter(event):
print 'frame enter'
w.widget().setFrameShape(3)
def mouse_leave(event):
print 'frame leave'
w.widget().setFrameShape(0)
for w in layout_widgets(window_layout):
print w.widget()
w.widget().enterEvent = mouse_enter
w.widget().leaveEvent = mouse_leave
window.show()
sys.exit(app.exec_())
It works but only the last frame in layout highlights.
How to make only that frame change its shape where the mouse is?
I've tried the following:
def mouse_enter(event, frame):
print 'frame enter'
frame.setFrameShape(3)
w.widget().enterEvent = functools.partial(mouse_enter, w.widget())
but it gives an error. I have found one more way to do that - signal mapper
but I have no idea how to use it.
The problem in your code the variable w when executing the for is left with the last element, so it will only be executed in the latter. To solve this I have implemented a Frame class that inherits from QFrame where I overwrite the enterEvent and leaveEvent functions.
from PyQt4 import QtGui, QtCore
import sys
class Frame(QtGui.QFrame):
def __init__(self, text, parent=None):
super(Frame, self).__init__(parent=parent)
label = QtGui.QLabel(text)
frame_layout = QtGui.QVBoxLayout()
frame_layout.addWidget(label)
self.setLayout(frame_layout)
def enterEvent(self, event):
self.setFrameShape(3)
def leaveEvent(self, event):
self.setFrameShape(0)
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window_layout = QtGui.QVBoxLayout()
window.setLayout(window_layout)
for i in range(10):
frame = Frame(str(i))
window_layout.addWidget(frame)
window.show()
sys.exit(app.exec_())
I want to display welcome label in middle of frame, how can I do that? It seems like layout problem as I googled but I haven't got final solution.
Here is the code:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Window(QMainWindow):
def __init__(self):
super(Window, self).__init__()
palette = QPalette()
palette.setBrush(QPalette.Background, QBrush(QPixmap("Login page.jpg")))
self.setPalette(palette)
self.setWindowTitle("Login Frame")
self.setWindowIcon(QIcon('logo.png'))
self.setGeometry(50, 50, 500, 300)
self.setFixedSize(500, 300)
self.addWidgets()
def addWidgets(self):
self.lblWelcome = QLabel("Welcome to Railway e-Ticketing System", self)
self.lblWelcome.move(100,30)
wcFont = QFont("Open Sans", 25)
self.lblWelcome.setFont(wcFont)
self.lblUid = QLabel("User ID:", self)
self.lblUid.move(100,80)
font = QFont("Open Sans", 10)
self.lneUid = QLineEdit(self)
self.lneUid.setFont(font)
self.lneUid.setFixedHeight(25)
self.lneUid.setFixedWidth(200)
self.lneUid.move(225, 80)
self.lblPass = QLabel("Password:", self)
self.lblPass.move(100, 130)
self.lnePass = QLineEdit(self)
self.lnePass.setEchoMode(QLineEdit.Password)
self.lnePass.setFixedHeight(25)
self.lnePass.setFixedWidth(200)
self.lnePass.move(225, 130)
self.lblInvalid = QLabel("",self)
self.lblInvalid.move(100, 180)
self.btnLogin = QPushButton("Login",self)
#btnLogin.resize(btnLogin.sizeHint())
self.btnLogin.move(175, 230)
self.btnLogin.clicked.connect(self.authenticate)
#self.authenticate()
self.btnReg = QPushButton("Register", self)
self.btnReg.move(300, 230)
#btnReg.clicked.connect(register)
self.show()
def authenticate(self):
uid = self.lneUid.text()
upass = self.lnePass.text()
if(len(uid.strip()) == 0 or len(upass.strip()) == 0):
palette = QPalette()
palette.setColor(QPalette.Foreground, Qt.darkRed)
self.lblInvalid.setPalette(palette)
self.lblInvalid.setText("*Invalid credentials .")
else:
self.lblInvalid.setText("")
def main():
app = QApplication(sys.argv)
LoginWin = Window()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
And here is the output:
You are using a QMainWindow which already has a layout with a central widget, a toolbar, a menu bar etc. The right way to use it is to define a central Widget, and put all your label and buttons in it. You didn't, so your label is not displayed properly.
But for your login frame, you clearly don't need all of this. You just need a QWidget:
import sys
from PyQt4 import QtCore,QtGui
class LoginFrame(QtGui.QWidget):
def __init__(self):
super(LoginFrame, self).__init__()
...
if __name__=='__main__':
app = QtGui.QApplication(sys.argv)
win = LoginFrame()
win.show()
sys.exit(app.exec_())
Your code should work with a QWidget, but I would still advise reading about box layout. Right now, you're using absolute positioning, which means you have to manually place your widget at a precise position, and you can't resize your window.
A box layout would be more flexible, and practical. For example you can use QFormLayout for the userID and password.
More about layouts on the ZetCode tutorial
I'm new guy, and i start with new simple GUI application, I follow some tutorial on the internet and now i have a trouble with QGroupbox (Pysde).
This is my code :
import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide import QtGui,QtCore
class Form(QtGui.QWidget):
def __init__(self,parent=None):
super(Form,self).__init__(parent)
self.initUi()
def initUi(self):
self.setGeometry(300, 300, 800, 600)
self.setWindowTitle('Library')
self.setMinimumHeight(600)
self.setMinimumWidth(800)
self.setMaximumHeight(600)
self.setMaximumWidth(1100)
#Groupbox Show Only
gpShowonly = QtGui.QGroupBox("Show only :")
gpShowonly.setGeometry(100,100,200,200)
chbx1 = QtGui.QCheckBox("x1")
chbx2 = QtGui.QCheckBox("x2")
chbx3 = QtGui.QCheckBox("x3")
serverlayout = QtGui.QHBoxLayout()
serverlayout.addWidget(chbx1)
serverlayout.addWidget(chbx2)
serverlayout.addWidget(chbx3)
configLayout = QtGui.QVBoxLayout()
configLayout.addLayout((serverlayout))
gpShowonly.setLayout(configLayout)
mainLayout = QtGui.QVBoxLayout()
mainLayout.addWidget(gpShowonly)
mainLayout.addStretch(1)
self.setLayout(mainLayout)
self.show()
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()
I want it's smaller but it's always full horizontal , I use setGeometry,resize but nothing happen.
The widgets inside a layout will expand to fill the available space. To prevent this, simply add an expandable spacer to the end of the layout:
serverlayout = QtGui.QHBoxLayout()
serverlayout.addWidget(chbx1)
serverlayout.addWidget(chbx2)
serverlayout.addWidget(chbx3)
serverlayout.addStretch()
If this makes the widgets too small, you could give them a minimum width:
for widget in chbx1, chbx2, chbx3:
widget.setMinimumWidth(100)