i'm trying to do a simple GUI for a python script that convert some text into a specific format but buttons doesn't show up in the window.
I first create the button class
class Button(QPushButton):
def __init__(self, btn_name=None):
super().__init__()
self.button = QPushButton(btn_name)
self.button.setCursor(
QCursor(QtCore.Qt.CursorShape.PointingHandCursor))
self.button.setStyleSheet(
"""*{border: 4px solid 'green';
border-radius: 45px;
font-size: 35px;
color: 'white';
padding: 25px 0;
margin: 100px, 200px}
*:hover{background: 'green'}
*:pressed{background: 'lightgreen'}"""
)
Then create the window class like this
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.window = QWidget()
self.window.resize(500, 500)
self.window.setWindowTitle("Pantuflis Software")
self.window.setFixedWidth(1000)
self.window.setStyleSheet("background: 'black';")
self.grid = QGridLayout()
self.window.setLayout(self.grid)
self.button = Button("Play")
self.grid.addWidget(self.button)
self.window.show()
Finally add the rest
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
But the button doesn't show up, only the main window does. I also tried the same but without creataing the button from my own class and works. Must be something wrong in the button class but i can't see what is.
If you are going to implement inherence then you have to apply the changes to the class. In your case it has a class that inherits from QPushButton but where you create the custom button which is not necessary, the same with the main window. My recommendation is that the OP should review his notes about inheritance.
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QCursor
from PyQt6.QtWidgets import QApplication, QGridLayout, QPushButton, QWidget
class Button(QPushButton):
def __init__(self, btn_name=""):
super().__init__(btn_name)
self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor))
self.setStyleSheet(
"""*{border: 4px solid 'green';
border-radius: 45px;
font-size: 35px;
color: 'white';
padding: 25px 0;
margin: 100px, 200px}
*:hover{background: 'green'}
*:pressed{background: 'lightgreen'}"""
)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(500, 500)
self.setWindowTitle("Pantuflis Software")
self.setFixedWidth(1000)
self.setStyleSheet("background: 'black';")
self.grid = QGridLayout(self)
self.button = Button("Play")
self.grid.addWidget(self.button)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
Related
I have a program where I display the GUI with PyQt5. From my MainWindow I open a QWidget from which a function is started. While this function is running a SplashScreen should appear. As soon as the function is finished, the SplashScreen should close again. I have tried to start the SplashScreen from within the function. However, the SplashScreen does not appear.
I have used the following code:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QProgressBar, QLabel, QFrame, QMainWindow, QVBoxLayout, QPushButton
from PyQt5.QtCore import Qt
import time
class Function:
def loading(self):
self.screen = SplashScreen()
self.screen.show()
time.sleep(10)
self.screen.close()
class SplashScreen(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle('Spash Screen Example')
self.setFixedSize(1100, 500)
self.setWindowFlag(Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
self.setWindowFlag(Qt.WindowStaysOnTopHint)
self.initUI()
def initUI(self):
layout = QVBoxLayout()
self.setLayout(layout)
self.frame = QFrame()
layout.addWidget(self.frame)
self.labelTitle = QLabel(self.frame)
self.labelTitle.setObjectName('LabelTitle')
# center labels
self.labelTitle.resize(self.width() - 10, 150)
self.labelTitle.move(0, 40) # x, y
self.labelTitle.setText('Splash Screen')
self.labelTitle.setAlignment(Qt.AlignCenter)
self.labelDescription = QLabel(self.frame)
self.labelDescription.resize(self.width() - 10, 50)
self.labelDescription.move(0, self.labelTitle.height())
self.labelDescription.setObjectName('LabelDesc')
self.labelDescription.setText('<strong>Working on Task #1</strong>')
self.labelDescription.setAlignment(Qt.AlignCenter)
self.progressBar = QProgressBar(self.frame)
self.progressBar.resize(self.width() - 200 - 10, 50)
self.progressBar.move(100, self.labelDescription.y() + 130)
self.progressBar.setAlignment(Qt.AlignCenter)
self.progressBar.setFormat('%p%')
self.progressBar.setTextVisible(True)
self.progressBar.setRange(0, 100)
self.progressBar.setValue(20)
self.labelLoading = QLabel(self.frame)
self.labelLoading.resize(self.width() - 10, 50)
self.labelLoading.move(0, self.progressBar.y() + 70)
self.labelLoading.setObjectName('LabelLoading')
self.labelLoading.setAlignment(Qt.AlignCenter)
self.labelLoading.setText('loading...')
self.setStyleSheet('''
#LabelTitle {
font-size: 60px;
color: #93deed;
}
#LabelDesc {
font-size: 30px;
color: #c2ced1;
}
#LabelLoading {
font-size: 30px;
color: #e8e8eb;
}
QFrame {
background-color: #2F4454;
color: rgb(220, 220, 220);
}
QProgressBar {
background-color: #DA7B93;
color: rgb(200, 200, 200);
border-style: none;
border-radius: 10px;
text-align: center;
font-size: 30px;
}
QProgressBar::chunk {
border-radius: 10px;
background-color: qlineargradient(spread:pad x1:0, x2:1, y1:0.511364, y2:0.523, stop:0 #1C3334, stop:1 #376E6F);
}
''')
class Window(QWidget):
def __init__(self):
super().__init__()
layout_window = QVBoxLayout()
self.setLayout(layout_window)
self.button = QPushButton("Open", self)
layout_window.addWidget(self.button)
self.button.clicked.connect(self.open)
def open(self):
self.function = Function()
self.function.loading()
class MyApp(QMainWindow):
def __init__(self):
super().__init__()
self.window_width, self.window_height = 1200, 800
self.setMinimumSize(self.window_width, self.window_height)
layout = QVBoxLayout()
self.setLayout(layout)
self.button = QPushButton("Open", self)
layout.addWidget(self.button)
self.button.clicked.connect(self.open)
def open(self):
self.window = Window()
self.window.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
myapp = MyApp()
myapp.show()
try:
sys.exit(app.exec_())
except SystemExit:
print('Closing Window...')
I have represented the function (in the original program some time consuming data processing takes place) with time.sleep. When I leave out the close-function, the 'SplashScreen' opens after the time.sleep is finished.
The time.sleep will block the event-loop, so any GUI-related operations will be suspended until it finishes. You therefore need to explicitly force processing of any pending events, using processEvents:
class Function:
def loading(self):
self.screen = SplashScreen()
self.screen.show()
for i in range(100):
self.screen.progressBar.setValue(i)
QApplication.processEvents()
time.sleep(0.1)
self.screen.close()
Or move the time-consuming task to a worker thread, and then use signals to update the GUI:
from PyQt5.QtCore import pyqtSignal, QThread
class Thread(QThread):
progressChanged = pyqtSignal(int)
def run(self):
for i in range(100):
QThread.msleep(100)
self.progressChanged.emit(i)
class Function:
def loading(self):
self.screen = SplashScreen()
self.screen.show()
self.thread = Thread()
self.thread.progressChanged.connect(
self.screen.progressBar.setValue)
self.thread.finished.connect(self.screen.close)
self.thread.start()
The latter approach is usually recommended, but if the task can't be broken up into discrete steps, you may need to use multiprocessing instead.
I'm trying to practise by making a Pokedex. I'm trying to dynamically create a list of buttons inside of an OVBoxLayout based on the response from an API call. The list of buttons is generated correctly however, none of the buttons work, code below:
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from app.pokeapi_client import PokeApiClient
class MainWindow(QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setup_styles()
self.pokemon_list_data = PokeApiClient().get_pokemon_list(limit=9)
self.setWindowTitle("Pokemon")
self.resize(1000, 800)
# create main layout
main_layout = QHBoxLayout()
# build list layout and populate with labels
self.pokemon_list_layout = QVBoxLayout()
self.populate_pokemon_list_layout()
# add list layout to main layout
main_layout.addLayout(self.pokemon_list_layout, 1)
self.setLayout(main_layout)
def populate_pokemon_list_layout(self):
for pokemon in self.pokemon_list_data['results']:
button = QPushButton(pokemon['name'])
button.clicked.connect(self.print_this)
self.pokemon_list_layout.addWidget(button)
def print_this(self):
print("hello world!")
def setup_styles(self):
self.setStyleSheet("""
QWidget {
background: red;
}
QPushButton {
color: white;
background: blue;
border: 1px solid white;
}
""")
The button.clicked.connect() doesn't appear to be assigning the function to each button, anyone know why this might be happening?
Here is a MRE with your code :
from PySide2 import QtWidgets
from PySide2 import QtCore
from PySide2 import QtGui
DATA = {'results':[{'name':'pikka'}, {'name': 'dracofeu'}, {'name': 'mewtwo'}]}
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.pokemon_list_data = DATA #Emulation data
self.setWindowTitle("Pokemon")
# self.resize(1000, 800)
# create main layout
main_layout = QtWidgets.QHBoxLayout()
# build list layout and populate with labels
self.pokemon_list_layout = QtWidgets.QVBoxLayout()
self.populate_pokemon_list_layout()
# add list layout to main layout
main_layout.addLayout(self.pokemon_list_layout, 1)
self.setLayout(main_layout)
def populate_pokemon_list_layout(self):
for pokemon in self.pokemon_list_data['results']:
button = QtWidgets.QPushButton(pokemon['name'])
button.clicked.connect(self.print_this)
self.pokemon_list_layout.addWidget(button)
def print_this(self):
sender = self.sender()
print(sender.text())
app = QtWidgets.QApplication([])
test = MainWindow()
test.show()
app.exec_()
Here is the result :
As you can see I didn't change anything (except imports and the sender in the print_this method) but it works. I think you have a problem somewhere in your code.
I have a QTabWidget and add a set label to his upper right corner. When I set the width and height of the label, its border crosses the 'a' tab I added. I want to set the width and height of lalel. Do not cross the 'a' tab I added, how should I set
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QTabWidget, QLabel
import sys
from PyQt4 import QtGui
class Setting(QLabel):
def __init__(self):
super(Setting, self).__init__()
self.setText('setting')
self.setStyleSheet("""*{border-width: 1px;
border-style: solid;
border-color: red;}""")
self.setFixedSize(30, 40)
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def create_tab(self):
self.tab = QTabWidget()
self.tab.addTab(QLabel('a'), 'a')
self.tab.setCornerWidget(Setting(), Qt.TopRightCorner)
def initUI(self):
self.create_tab()
h = QtGui.QHBoxLayout()
self.setLayout(h)
h.addWidget(self.tab)
self.setGeometry(100, 100, 500, 500)
self.show()
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
If you remove the setFixedSize() from your label you can control the size and position through a stylesheet on the QTabWidget by targetting ::right-corner.
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def create_tab(self):
self.tab = QTabWidget()
self.tab.setStyleSheet('''
QTabWidget::right-corner {
width: 60px;
height: 25px;
subcontrol-position: left bottom;
}''')
self.tab.addTab(QLabel('a'), 'a')
self.tab.setCornerWidget(Setting(), Qt.TopRightCorner)
Instead of subcontrol-position you can also use top, bottom, left and right with pixel values to shift the control around.
I am developing an application in Python using PyQt5. Here is the code in question:
class Dialog(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.layout = QtWidgets.QGridLayout()
self.main = QtWidgets.QWidget()
self.main.setLayout(self.layout)
self.setStyleSheet(QMainWindowStyle)
self.setCentralWidget(self.main)
self.show()
class AppearanceTab(QtWidgets.QWidget):
def __init__(self):
super().__init__()
class SettingsDialog(Dialog):
def __init__(self):
super().__init__()
self.tabs = QtWidgets.QTabWidget(self)
self.tabs.setStyleSheet(QTabWidgetStyle)
self.layout.addWidget(self.tabs)
self.tab_appearance = AppearanceTab()
self.tab_appearance.setStyleSheet(QWidgetStyle)
self.tab_appearance_layout = QtWidgets.QGridLayout()
self.tab_appearance.setLayout(self.tab_appearance_layout)
self.tabs.addTab(self.tab_appearance, "Appearance")
self.tab_server = QtWidgets.QWidget()
self.tab_server.setStyleSheet(QWidgetStyle)
self.tab_server_layout = QtWidgets.QGridLayout()
self.tab_server.setLayout(self.tab_server_layout)
self.tabs.addTab(self.tab_server, "Server")
Why is it that when self.tab_appearance is an AppearanceTab instance (which should be a copy of QWidget) it has a different style to self.tab_server (i.e. background colour changes) when self.tab_server is an instance of QWidget?
The stylesheet just defines background-color: #333333 and color: #dddddd.
Thanks in advance.
EDIT:
I believe that the stylesheet is not being properly applied to AppearanceTab, however I don;t know why that would be seeing as it just inherits from QWidget.
EDIT 2:
A MCVE (along with the rest of my project) can be found on github.
In the documentation, there is a paragraph the paragraph about inheritance and style:
Inheritance
In classic CSS, when font and color of an item is not explicitly set, it gets automatically inherited from the parent. When using Qt Style Sheets, a widget does not automatically inherit its font and color setting from its parent widget.
If we want to set the color on a QGroupBox and its children, we can write:
qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");
So you probably want to to change
QMainWindowStyle = QMainWindow {color: #dddddd; background-color: #333333;}
to
QMainWindowStyle = QMainWindow, QMainWindow * {color: #dddddd; background-color: #333333;}
so that all the child widgets of the main window have the same style.
Try it:
from PyQt5 import QtWidgets
class Dialog(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.layout = QtWidgets.QGridLayout()
self.main = QtWidgets.QWidget()
self.main.setLayout(self.layout)
# self.setStyleSheet(QMainWindowStyle)
self.setCentralWidget(self.main)
self.show()
class AppearanceTab(QtWidgets.QWidget):
def __init__(self):
super().__init__()
class SettingsDialog(Dialog):
def __init__(self):
super().__init__()
self.tabs = QtWidgets.QTabWidget(self)
# self.tabs.setStyleSheet(QTabWidgetStyle)
self.layout.addWidget(self.tabs)
self.tab_appearance = AppearanceTab()
# self.tab_appearance.setStyleSheet(QWidgetStyle)
## self.tab_appearance.setStyleSheet("QWidget, QWidget * {color: #dddddd; background-color: #333333;}") #note: Tried this however it didn't work.
self.tab_appearance_layout = QtWidgets.QGridLayout()
self.tab_appearance.setLayout(self.tab_appearance_layout)
self.tabs.addTab(self.tab_appearance, "Appearance")
self.tab_server = QtWidgets.QWidget()
# self.tab_server.setStyleSheet(QWidgetStyle)
self.tab_server_layout = QtWidgets.QGridLayout()
self.tab_server.setLayout(self.tab_server_layout)
self.tabs.addTab(self.tab_server, "Server")
style = """
QWidget {
color: #dddddd;
background-color: #333333;
}
QMainWindow {
color: #dddddd;
background-color: #333333;
}
QTabWidget {
background-color: #333333;
color: #dddddd;
}
QTabBar {
color: #dddddd;
background-color: #333333;
}
"""
if __name__ == "__main__":
QtWidgets.QApplication.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
app = QtWidgets.QApplication([])
app.setStyleSheet(style) # < ---
d = SettingsDialog()
print(app.exec_())
I have a QDialog which contains a QGroupBox which in turn contains some push-buttons. I want to differentiate the background-color of the push-button which is clicked and all the remaining push-buttonx. How to achieve this?
Make sure the buttons are all children of the group-box, and then use findChildren to iterate over them. You could also use a QButtonGroup to help manage the buttons.
Here's a demo script to show how it could be done:
from PyQt5 import QtCore, QtWidgets
class Dialog(QtWidgets.QDialog):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout(self)
self.groupBox = QtWidgets.QGroupBox(self)
layout.addWidget(self.groupBox)
layout = QtWidgets.QVBoxLayout(self.groupBox)
for index in range(5):
button = QtWidgets.QPushButton('Button %d' % index, self.groupBox)
layout.addWidget(button)
self.buttonGroup = QtWidgets.QButtonGroup(self)
self.buttonGroup.buttonClicked.connect(self.handleButtonClicked)
self.updateButtonGroup()
def updateButtonGroup(self):
for button in self.groupBox.findChildren(QtWidgets.QPushButton):
if self.buttonGroup.id(button) < 0:
self.buttonGroup.addButton(button)
def handleButtonClicked(self, button):
for item in self.buttonGroup.buttons():
if button is item:
item.setStyleSheet('background-color: orange')
else:
item.setStyleSheet('')
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Dialog()
window.show()
sys.exit(app.exec_())
If reason to use class QtGui.QGroupBox is select button just like radio button, You can use Qt Style Sheet to set difference background color;
import sys
from PyQt4 import QtGui
class QCustomDialog (QtGui.QDialog):
def __init__(self, *args, **kwargs):
QtGui.QDialog.__init__(self, *args, **kwargs)
myQVBoxLayout = QtGui.QVBoxLayout()
for text in ['PyQt', 'Stack', 'Overflow']:
myQPushButton = QtGui.QPushButton(text)
myQPushButton.setCheckable(True)
myQPushButton.setAutoExclusive(True)
myQVBoxLayout.addWidget(myQPushButton)
myQVBoxLayout.addStretch(1)
myQGroupBox = QtGui.QGroupBox()
myQGroupBox.setStyleSheet('''
QPushButton {
border: 0px;
color: rgb(255, 255, 255);
background-color: rgb(0, 0, 0);
}
QPushButton:checked {
border: 0px;
color: rgb(255, 255, 255);
background-color: rgb(255, 0, 0);
}
''')
myQGroupBox.setLayout(myQVBoxLayout)
allQVBoxLayout = QtGui.QVBoxLayout()
allQVBoxLayout.addWidget(myQGroupBox)
self.setLayout(allQVBoxLayout)
myQApplication = QtGui.QApplication([])
myQCustomDialog = QCustomDialog()
myQCustomDialog.show()
sys.exit(myQApplication.exec_())