I read that it is possible to use a simple QWidget as Layout for a page of a QTabWidget, so that I can design the tab page the way I want it.
How do I implement that?
One of the functionalities of a QWidget is to be a container so it is only necessary to add it in each tab:
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.tab_widget = QtWidgets.QTabWidget()
self.setCentralWidget(self.tab_widget)
page1 = QtWidgets.QWidget()
page2 = QtWidgets.QWidget()
for page, title in ((page1, "Page1"), (page2, "Page2")):
self.tab_widget.addTab(page, title)
lay1 = QtWidgets.QVBoxLayout(page1)
for i in range(3):
lay1.addWidget(
QtWidgets.QLabel(f"label{i}", alignment=QtCore.Qt.AlignCenter)
)
lay1.addStretch()
lay2 = QtWidgets.QVBoxLayout(page2)
for i in range(4):
lay2.addWidget(QtWidgets.QPushButton(f"button {i}"))
lay2.addStretch()
self.resize(640, 480)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())
Related
This question already has an answer here:
How to open a window with a click of a button from another window using PyQt?
(1 answer)
Closed 3 years ago.
I want to create a new window when a button is clicked. I will later have windows be created dynamically depending on inputted data. But I want to start simple first.
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QGridLayout, QWidget
class MyWindow(QtWidgets.QMainWindow, QPushButton):
def __init__(self):
super(MyWindow, self).__init__()
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.setWindowTitle("ASSET")
self.Button = QPushButton('Action',self)
self.Button.clicked.connect(self.Action)
self.layout = QGridLayout(centralWidget)
self.layout.addWidget(self.Button)
def Action(self):
pass
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
You can create another QMainWindow() and when the button is clicked, activate the show() method
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QPushButton, QGridLayout, QWidget, QLabel
class NewWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(NewWindow, self).__init__(parent)
self.label = QLabel('New Window!')
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.layout = QGridLayout(centralWidget)
self.layout.addWidget(self.label)
class MyWindow(QtWidgets.QMainWindow, QPushButton):
def __init__(self):
super(MyWindow, self).__init__()
centralWidget = QWidget()
self.setCentralWidget(centralWidget)
self.setWindowTitle("ASSET")
self.Button = QPushButton('Action',self)
self.Button.clicked.connect(self.Action)
self.layout = QGridLayout(centralWidget)
self.layout.addWidget(self.Button)
self.new_window = NewWindow(self)
def Action(self):
self.new_window.show()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
I'm using PyQt5, QMainWindow and I want to change default position of toolbar to the right. How can I do it?
User can carry toolbar to the edges of the window using mouse, but how can I do it using program?
def initUI(self):
self.toolbar = self.addToolBar('Example')
You have to use the addToolBar method as shown below:
import sys
from PyQt5 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.initUI()
def initUI(self):
self.toolbar = QtWidgets.QToolBar("Example")
self.addToolBar(QtCore.Qt.RightToolBarArea, self.toolbar)
self.toolbar.addAction("action 1")
self.toolbar.addAction("action 2")
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
I am trying to make the last QPushButton visible by using method QScrollArea().ensureWidgetVisible(), but as you can see this method doesn't scroll till the last QPushButton.
Example
Could you please assist and solve my issue perhaps issue with setFrameStyle? thank you in advance.
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Widget(QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__()
self.setFixedHeight(200)
#Container Widget
widget = QWidget()
#Layout of Container Widget
layout = QVBoxLayout(self)
for _ in range(20):
btn = QPushButton("test")
layout.addWidget(btn)
widget.setLayout(layout)
#Scroll Area Properties
scroll = QScrollArea()
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
# print(scroll.verticalScrollBar().maximum())
# vbar = scroll.verticalScrollBar()
# vbar.setValue(vbar.maximum())
#vbar.setValue(vbar.maximum())
#Scroll Area Layer add
vLayout = QVBoxLayout(self)
vLayout.addWidget(scroll)
self.setLayout(vLayout)
# items = (layout.itemAt(i) for i in range(layout.count()))
# for w in items:
# print(w)
print(layout.count())
#scroll.ensureWidgetVisible(layout.itemAt(layout.count()-5).widget(), xMargin=10, yMargin=10 )
scroll.ensureWidgetVisible(layout.itemAt(layout.count()-1).widget() )
print(layout.itemAt(layout.count()-1).widget(),"last widget")
if __name__ == '__main__':
app = QApplication(sys.argv)
dialog = Widget()
dialog.show()
app.exec_()
The problem is that for efficiency reasons widgets sizes are not calculated or updated until they are displayed, in your case the viewport of QScrollArea has not updated its size and therefore moves the scroll to an intermediate position. A possible solution is to use QTimer::singleShot() to call the function ensureWidgetVisible() a moment after it has been displayed:
import sys
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent= None):
super(Widget, self).__init__(parent)
self.setFixedHeight(200)
#Container Widget
widget =QtWidgets.QWidget()
#Layout of Container Widget
layout = QtWidgets.QVBoxLayout(widget)
for _ in range(20):
btn = QtWidgets.QPushButton("test")
layout.addWidget(btn)
scroll = QtWidgets.QScrollArea()
scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(False)
scroll.setWidget(widget)
#Scroll Area Layer add
vLayout = QtWidgets.QVBoxLayout(self)
vLayout.addWidget(scroll)
last_widget = layout.itemAt(layout.count()-1).widget()
QtCore.QTimer.singleShot(0, partial(scroll.ensureWidgetVisible, last_widget))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dialog = Widget()
dialog.show()
sys.exit(app.exec_())
or simply call show() before:
...
last_widget = layout.itemAt(layout.count()-1).widget()
self.show()
scroll.ensureWidgetVisible(last_widget)
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'm totally new to PyQt5 and I'm trying to develop an application with a main menu and sub menus and i don't know how to start. All examples that I found are using that pop up windows as sub menu.
Here is an example of what I'm going to do. Any suggestion on how to start and what to use in PyQt5 please ?
The main menu is on the right and a sub menu is on the left
To make the main menu you can use QListWidget in the icon mode, and to exchange the pages you can use QStackedLayout:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Page(QtWidgets.QWidget):
clicked = QtCore.pyqtSignal()
def __init__(self, content, parent=None):
super(Page, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
button = QtWidgets.QPushButton("Back")
button.clicked.connect(self.clicked)
lay.addWidget(button)
lay.addWidget(content)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
self.stacked = QtWidgets.QStackedWidget()
lay.addWidget(self.stacked)
self.listWidget = QtWidgets.QListWidget()
self.listWidget.setViewMode(QtWidgets.QListView.IconMode)
self.listWidget.setIconSize(QtCore.QSize(128, 128))
self.listWidget.itemClicked.connect(self.onItemClicked)
self.stacked.addWidget(self.listWidget)
for icon, content in [("alarms.png", QtWidgets.QTextEdit() ),
("fitness.png", QtWidgets.QMdiArea() ),
("navigation.png", QtWidgets.QTableWidget(4, 4) ),
("notifications.png", QtWidgets.QListWidget() )]:
p = Page(content)
p.clicked.connect(lambda: self.stacked.setCurrentIndex(0))
self.addPage(QtGui.QIcon(icon), p)
def addPage(self, icon, widget):
it = QtWidgets.QListWidgetItem()
it.setIcon(icon)
self.listWidget.addItem(it)
self.stacked.addWidget(widget)
it.setData(QtCore.Qt.UserRole, self.listWidget.count())
def onItemClicked(self, it):
ix = it.data(QtCore.Qt.UserRole)
self.stacked.setCurrentIndex(ix)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())