I've been pulling my hairs on this since a few hours. I have the following simple example:
#!/usr/bin/env python
import math
from PyQt5.QtCore import (pyqtSignal, QLineF, QPointF, QRect, QRectF, QSize,
QSizeF, Qt)
from PyQt5.QtGui import (QBrush, QColor, QFont, QIcon, QIntValidator, QPainter,
QPainterPath, QPen, QPixmap, QPolygonF)
from PyQt5.QtWidgets import (QAction, QApplication, QButtonGroup, QComboBox,
QFontComboBox, QGraphicsItem, QGraphicsLineItem, QGraphicsPolygonItem,
QGraphicsScene, QGraphicsTextItem, QGraphicsView, QGridLayout,
QHBoxLayout, QLabel, QMainWindow, QMenu, QMessageBox, QSizePolicy,
QToolBox, QToolButton, QWidget)
class DiagramScene(QGraphicsScene):
def __init__(self, parent=None):
super(DiagramScene, self).__init__(parent)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.scene = DiagramScene()
self.scene.setSceneRect(QRectF(0, 0, 5000, 5000))
layout = QHBoxLayout()
self.view = QGraphicsView(self.scene)
layout.addWidget(self.view)
self.widget = QWidget()
self.widget.setLayout(layout)
self.setCentralWidget(self.widget)
self.setWindowTitle("Diagramscene")
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.setGeometry(100, 100, 800, 500)
mainWindow.show()
sys.exit(app.exec_())
This program works OK. Now if you replace
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.setGeometry(100, 100, 800, 500)
mainWindow.show()
sys.exit(app.exec_())
by this (which is what you do when you want to start your program with console_scripts):
def mainFunc():
import sys
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.setGeometry(100, 100, 800, 500)
mainWindow.show()
sys.exit(app.exec_())
if __name__ == '__main__':
mainFunc()
I get a segfault on exit. Althout both programs are (apparently ?) IDENTICALS.
It should be noted that if you remove the QGraphicsView from the application, the bug goes away. No more segfault on exit.
Is the issue coming from my code ? Or is it a PyQt5 bug ?
As pointed-out by #user3419537, the catch here is to always provide a parent on widget construction.
Otherwise, deallocation goes south and you end up with a nice segfault on program termination.
The following modified code works correctly:
#!/usr/bin/env python
import math
from PyQt5.QtCore import (QLineF, QPointF, QRect, QRectF, QSize,
QSizeF, Qt)
from PyQt5.QtGui import (QBrush, QColor, QFont, QIcon, QIntValidator, QPainter,
QPainterPath, QPen, QPixmap, QPolygonF)
from PyQt5.QtWidgets import (QAction, QApplication, QButtonGroup, QComboBox,
QFontComboBox, QGraphicsItem, QGraphicsLineItem, QGraphicsPolygonItem,
QGraphicsScene, QGraphicsTextItem, QGraphicsView, QGridLayout,
QHBoxLayout, QLabel, QMainWindow, QMenu, QMessageBox, QSizePolicy,
QToolBox, QToolButton, QWidget)
class DiagramScene(QGraphicsScene):
def __init__(self, parent=None):
super(DiagramScene, self).__init__(parent)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
# Build Widgets, from top to bottom
# Always assigning a parent to it
## widget is attached to MainWindow
self.widget = QWidget(self)
## view is attached to widget (main area of the MainWindow)
self.view = QGraphicsView(self.widget)
## scene is attached to the view
self.scene = DiagramScene(self.view)
# Configure the widgets
self.view.setScene(self.scene)
# Configure the layout
layout = QHBoxLayout()
layout.addWidget(self.view)
self.widget.setLayout(layout)
self.setCentralWidget(self.widget)
self.setWindowTitle("Diagramscene")
def mainFunc():
import sys
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.setGeometry(100, 100, 800, 500)
mainWindow.show()
sys.exit(app.exec_())
if __name__ == '__main__':
mainFunc()
Related
I'm designing window with PyQt5 and QtDesigner. I made maindemo.py, maindemo.ui, mainfail.py, mainfail.ui.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QGraphicsView, QLabel, QMenuBar, QMenu, QStatusBar, QAction, qApp, QMessageBox
from PyQt5 import uic, QtCore
form_class = uic.loadUiType("maindemo.ui")[0]
class OpeningWindow(QMainWindow, form_class):
def __init__(self):
super().__init__()
self.setupUi(self)
self.initUI()
def initUI(self):
self.setWindowTitle('Qomics')
self.btn_survival.setToolTip('Survival Analysis')
self.btn_drug.setToolTip('Drug Analysis')
self.btn_CRISPR.setToolTip('CRISPR Analysis')
self.btn_cellline.setToolTip('Cell Line')
self.btn_survival.clicked.connect(self.open_SurvivalMainWindow)
self.btn_drug.clicked.connect(self.open_DrugWindow)
self.btn_CRISPR.clicked.connect(self.open_sgRNAWindow)
self.btn_cellline.clicked.connect(self.open_CellLineWindow)
actionExit = QAction('&Exit', self)
actionExit.setShortcut('Ctrl+Q')
actionExit.setStatusTip('Exit Application')
actionExit.triggered.connect(qApp.quit)
self.statusBar().showMessage('abcd')
self.setGeometry(200, 100, 800, 530)
self.show()
def openSurvivalMainWindow(self):
open_SurvivalMainWindow = SurvivalMainWindow()
open_SurvivalMainWindow.show()
def openDrugWindow(self):
open_DrugWindow = DrugWindow()
open_DrugWindow.show()
def opensgRNAWindow(self):
open_sgRNAWindow = sgRNAWindow()
open_sgRNAWindow.show()
def openCellLineWindow(self):
open_CellLineWindow = scatterWindow()
open_CellLineWindow.show()
above code is maindemo.py
what I want to do is clicking btn_drug, btn_sgRNA, btn_cellline connects to new window(with mainfail.py, mainfail.ui)
Only btn_survival connects to the real function and other buttons connects to mainfail window.
I tried to use if, else... but I couldn't write proper code..
I wrote a code but it doesn't work.
if openSurvivalMainWindow():
else:
openMainFailWindow.show()
Not clear what you want, but here an example of a multi window
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QGraphicsView, QLabel, QMenuBar, QMenu, QStatusBar, QAction, qApp, QMessageBox
from PyQt5 import uic, QtCore
from PyQt5.uic import loadUiType
login, _ = loadUiType('login.ui')
registration,_ = loadUiType('registration.ui')
class Register(QMainWindow, registration):
def __init__(self):
QWidget.__init__(self)
self.setupUi(self)
self.pushButton_24.clicked.connect(self.adding_users)
self.pushButton_25.clicked.connect(self.return_login)
def return_login(self):
self.window2 = Login()
self.close()
self.window2.show()
class Login(QWidget, login):
def __init__(self):
QWidget.__init__(self)
self.setupUi(self)
self.pushButton.clicked.connect(self.Handel_Login)
self.pushButton_2.clicked.connect(self.registrations)
def registrations(self):
self.window2 = Register()
self.close()
self.window2.show()
######
#....
######
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle('Fusion')
window = Login()
#window = MainApp()
window.show()
sys.exit(app.exec_())
With this your application will go first to the login page and if you push the button 2 you will go to the registration page and of course the log in page will be closed
everyone.
I want to float a widget inside a layout of a main-window.
the widget is disappered from layout but not displayed on screen
As you can see from following code. I floated two labels 'lbl_title' and 'lbl_icon'
they seems to be floated but not displayed on screen.
Here comes my code.
If you loose commented line, then the lbl_icon and title is removed from layout but not are shown on my screen
from PyQt5.QtCore import QDir, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import (QApplication, QFileDialog, QHBoxLayout, QLabel,
QPushButton, QSizePolicy, QSlider, QStyle, QVBoxLayout, QWidget)
from PyQt5.QtWidgets import QMainWindow,QWidget, QPushButton, QAction,QGridLayout
from PyQt5.QtGui import QIcon,QPixmap
import sys
from PyQt5.QtCore import *
class CommonLessonItem(QWidget):
def __init__(self,parent):
super(CommonLessonItem,self).__init__(parent)
self.lbl_title = QLabel(self)
self.lbl_description = QLabel(self)
self.lbl_icon = QLabel(self)
self.__initUI()
self.isChild = False
def __initUI(self):
#set layout
self.layout = QGridLayout(self)
self.layout.addWidget(self.lbl_title,0,0,1,19)
self.layout.addWidget(self.lbl_icon,0,19,1,1)
self.layout.addWidget(self.lbl_description,1,0,1,20)
self.lbl_icon.setWindowFlags(Qt.FramelessWindowHint|Qt.Window)
self.lbl_icon.move(100,100)
self.lbl_title.setWindowFlags(Qt.FramelessWindowHint|Qt.Window)
self.lbl_title.move(100,100)
#initialize info
self.setInfo("Title","Description",None)
self.setLayout(self.layout)
def setInfo(self,title,description,iconPath):
self.lbl_title.setText(title)
self.lbl_description.setText(description)
if(iconPath is not None):
self.lbl_icon.setPixmap(QPixmap(iconPath))
def moveEvent(self,event):
super().moveEvent(event)
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = CommonLessonItem(None)
# mw.setSize(10,200)
mw.show()
sys.exit(app.exec_())
I need your help.
Whenever a widget becomes a top level window by setting the parent to None or, like in your case, setting the Window flag (but I wouldn't suggest that approach) show() must be called.
As explained in windowFlags:
Note: This function calls setParent() when changing the flags for a window, causing the widget to be hidden. You must call show() to make the widget visible again..
Add self.lbl_icon.show() and self.lbl_title.show() after changing their window state.
I have a program that displays some message on a label (using QtDesigner):
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow
class MyWidget(QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi('main1.ui', self)
self.run()
def run(self):
self.label.setText('Message')
app = QApplication(sys.argv)
ex = MyWidget()
ex.show()
sys.exit(app.exec_())
This message displays in the selected font in the QtDesigner, StyleSheet of my label:
The question is: What can I do to make this font be randomly selected? Is it possible? (Perfect case: every time i run my program it shows my message in some randomly selected font)
You can obtain all the available families through the families() method of QFontDatabase, choose one randomly, build a QFont and set it in the QLabel:
import random
import sys
from PyQt5 import uic
from PyQt5.QtGui import QFont, QFontDatabase
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow
class MyWidget(QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi("main1.ui", self)
db = QFontDatabase()
family = random.choice(db.families())
print(family)
font = db.font(family, "", 72)
# also random style:
# style = random.choice(db.styles(family))
# font = db.font(family, style, 72)
self.label.setFont(font)
self.run()
def run(self):
self.label.setText("Message")
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = MyWidget()
ex.show()
sys.exit(app.exec_())
Hi, I have an issue with my PyQt5 setWindowIcon.
When I try to set my window icon from a local image, it works perfectly. But when I try to put a online link like:
setWindowIcon( QIcon("https://www.google.ge/images/branding/product/ico/googleg_lodp.ico") )
it does not work. What to do? Its 32x32 ico btw.
~Thanks
You have to use QNetworkAccessManager and manually download image from url. Then read bytes from response, create a QPixmap (beacuse it has loadFromData method) and initialize a QIcon from QPixmap.
And after that you will be able to set window icon.
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout
ICON_IMAGE_URL = "https://www.google.ge/images/branding/product/ico/googleg_lodp.ico"
class MainWindow(QWidget):
def __init__(self):
QWidget.__init__(self)
self.label = QLabel('Image loading demo')
self.vertical_layout = QVBoxLayout()
self.vertical_layout.addWidget(self.label)
self.setLayout(self.vertical_layout)
self.nam = QNetworkAccessManager()
self.nam.finished.connect(self.set_window_icon_from_response)
self.nam.get(QNetworkRequest(QUrl(ICON_IMAGE_URL)))
def set_window_icon_from_response(self, http_response):
pixmap = QPixmap()
pixmap.loadFromData(http_response.readAll())
icon = QIcon(pixmap)
self.setWindowIcon(icon)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
I was writing a pyqt5 program for expression evaluator but after running the program i am not able to see any widgets and getting blank window
def expressionevaluator():
import sys
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QWidget,QMainWindow
class Window(QtWidgets.QMainWindow):
def __init__(self):
super(Window,self).__init__()
self.setGeometry(50,50,500,300)
self.setWindowTitle("PyQt Tutorial")
self.setWindowIcon=QtGui.QIcon('pyqt_example2.PNG')
self.home()
def ExitForm(self):
sys.exit()
def home(self):
vbox=QtWidgets.QVBoxLayout()
textbrowser=QtWidgets.QTextBrowser()
lineedit=QtWidgets.QLineEdit()
btn=QtWidgets.QPushButton("QUIT")
btn.clicked.connect(self.close)
vbox.addWidget(textbrowser)
vbox.addWidget(lineedit)
vbox.addWidget(btn)
self.setLayout(vbox)
self.show()
if __name__=="__main__":
app=QApplication(sys.argv)
GUI=Window()
sys.exit(app.exec_())
expressionevaluator()
So what should I do ?
Just running your code I got a widget showing up in my screen, but its components didn't show up. Instead of setting a layout of a QMainWindow try to have a central widget (QWidget) set its layout with its components than set the QMainWindow central widget with this widget. There you go, now you have all working fine.
You had problems with the layout because QMainWindow behaves differently from others Widgets, it has its own layout and many other default behaviors, central widget is the reason why nothing was showing up inside your main window.
def expressionevaluator():
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QTextBrowser
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget
class Window(QMainWindow):
def __init__(self):
super(Window,self).__init__()
self.setGeometry(50,50,500,300)
self.setWindowTitle("PyQt Tutorial")
self.setWindowIcon = QIcon('pyqt_example2.PNG')
self.home()
def ExitForm(self):
sys.exit()
def home(self):
vbox = QVBoxLayout()
textbrowser = QTextBrowser()
lineedit = QLineEdit()
btn = QPushButton("QUIT")
central_widget = QWidget()
central_widget.setLayout(vbox)
btn.clicked.connect(self.close)
vbox.addWidget(textbrowser)
vbox.addWidget(lineedit)
vbox.addWidget(btn)
self.setCentralWidget(central_widget)
self.show()
if __name__=="__main__":
app = QApplication(sys.argv)
GUI = Window()
GUI.show()
sys.exit(app.exec_())
expressionevaluator()
Note: There are many improvements in the structure of your code you could do, I just changed as less as I could to make it work, for example try to not import all the modules at once, import just what you need for example QIcon, QLineEdit and so on, instead of the whole QtWidgets, or QtCore...
Following code works well:
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QTextBrowser
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget
class Window(QMainWindow):
def __init__(self):
super(Window,self).__init__()
self.setGeometry(50,50,500,300)
self.setWindowTitle("PyQt Tutorial")
self.setWindowIcon = QIcon('pyqt_example2.PNG')
self.home()
def ExitForm(self):
sys.exit()
def home(self):
vbox = QVBoxLayout()
textbrowser = QTextBrowser()
lineedit = QLineEdit()
btn = QPushButton("QUIT")
central_widget = QWidget()
central_widget.setLayout(vbox)
btn.clicked.connect(self.ExitForm)
vbox.addWidget(textbrowser)
vbox.addWidget(lineedit)
vbox.addWidget(btn)
self.setCentralWidget(central_widget)
self.show()
if __name__=="__main__":
app = QApplication(sys.argv)
GUI = Window()
GUI.show()
sys.exit(app.exec_())