PyQt5 WindowsVista style instead of Win10 style - python

When I design a UI with PyQt5, in Qt Designer it looks like win10 app. But when I start a program in VS Code or just run a file, it looks like in Windows Vista or 7. How to fix that? I haven't changed style in the code
import os
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import QApplication, QMainWindow
class UI(QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi(os.path.join(sys.path[0], 'untitled.ui'), self)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = UI()
ex.show()
sys.exit(app.exec())
how it looks in designer
how it really looks

You can change the display style by using app.setStyle. To get a list of available styles on your system try this:
from PyQt5.QtWidgets import QStyleFactory
print(QStyleFactory.keys())
on my system I get:
['Breeze', 'Oxygen', 'Windows', 'Fusion']
Probably you'll get difference choices on a Windows box.
To evaluate different styles try:
app.setStyle('<style name here>')
or
app.setStyle(QStyleFactory.create('style name here'))

Related

QtCreator's UI is not applied to the window, it's always empty (Qt for Python)

I have a fresh QtCreator installation, and I set it up to run using a fresh install of Python3.8 on which I pip-installed both pyside2 and pyside6.
When I create a new Qt for Python - Window (UI file) application, whatever I do to the UI file the window always shows up empty and with the default size when I run the app.
I've tried with a QDialog, QMainApplication, using Pyside2 or Pyside6, I've checked that it was correctly loading the UI (and the right one) - no dice. It just won't update, and appears not to have any reason not to.
Default code for completeness:
# This Python file uses the following encoding: utf-8
import os
from pathlib import Path
import sys
from PySide2.QtWidgets import QApplication, QDialog
from PySide2.QtCore import QFile
from PySide2.QtUiTools import QUiLoader
class Dialog(QDialog):
def __init__(self):
super(Dialog, self).__init__()
self.load_ui()
def load_ui(self):
loader = QUiLoader()
path = os.fspath(Path(__file__).resolve().parent / "form.ui")
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
loader.load(ui_file, self)
ui_file.close()
if __name__ == "__main__":
app = QApplication([])
widget = Dialog()
widget.show()
sys.exit(app.exec_())
(In the UI I just drag-dropped a button right in the middle and saved the file)
Am I forgetting something fundamental? I'm only used to programming in C++ using QtCreator.
I was expecting this to work right out of the box, but it's not.
This only dynamically load the UI as a new widget, with this custom class as a parent.
If I want signals and slots to work, the only thing I've found was to add a custom build step:
Command: <path to pyside6 install, use pip show to know where>\uic.exe
Arguments: <filename of the .ui file> -o <the python translation .py
which will serve as baseclass> -g python
Working directory: [your project dir]
Then signals and slots need to be connected manually, so QtCreator really only enables you to draw the user interface but all the logic still needs to be done by hand. Component variables are normally named after their UI name, but you can see for yourself in the baseclass file. This is a big step back from how QtCreator is used in C++ ("go to slot" will not work).
Code to use:
import sys
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCore import QFile
from PySide6.QtUiTools import QUiLoader
from YourGenPyFileName import Ui_YourUIName
class MainWindow(QMainWindow, Ui_YourUIName):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)
if __name__ == "__main__":
app = QApplication([])
widget = MainWindow()
widget.show()
sys.exit(app.exec_())

Why is the word wrap (QTableWidget, PYQT5) painted differently when running .py from cmd than running with anaconda prompt?

I wrote a GUI in pyqt5 where you can enter two paths (file paths, directory paths, ...). Now my problem is the following:
(1) when I run it with the Anaconda Prompt window, and enter any longer path then it does the word wrap how I want it (and afai can tell correctly):
in this case using setTextElideMode works as well.
(2) when I run it with the windows command prompt (C:\[...]\Desktop>C:\[...]\python\3.8.1.0.0\python-3.8.1.amd64\python.exe C:\[...]\Desktop\cmd_problems.py) it begins wrapping the text directly after "C:" by inserting the normal ellipsis "..." - I have to stretch the column (manually) until the whole path is visible to make it show more than that:
using setTextElideMode does nothing.
Does anyone know how to get the first behavior when running the code from the windows cmd line? (I need this because I use a batch script to launch the program similar to making an .exe file.)
Here is my code:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from PyQt5.QtWidgets import QTableWidget, QVBoxLayout
class MyWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Very Important Window")
cen = QWidget()
self.layout = QVBoxLayout()
self.setCentralWidget(cen)
cen.setLayout(self.layout)
self.tbl = QTableWidget()
self.tbl.setRowCount(1)
self.tbl.setColumnCount(2)
self.tbl.setTextElideMode(Qt.ElideRight)
col_names = ["FROM", "TO"]
self.tbl.setHorizontalHeaderLabels(col_names)
self.layout.addWidget(self.tbl)
def main():
app = QApplication([])
win = MyWindow()
win.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

How to determine what to import for, for example, the matchFlags used with QTreeWidget.findItems?

I am trying to use function QTreeWidget.findItems to find an exact match (the item is named "Things")
I saw an example using this ... Qt.MatchExactly ... as the 'match flag'.
even though i had imported Qt module from PyQt5, the MatchExactly was not found.
I got it to work by importing ANOTHER Qt module found in QtCore in PyQt5. but that was after many hours over several days of poking, guessing, and reading stackOverFlow posts.
My question is - how to know what module contains (and therefore must be imported) the stuff I need? how would I know that Qt.MatchExactly is in the PyQt5.QtCore.Qt module (and NOT in PyQt5.Qt module)?
This is my code: Note it reads in a QtDesigner .ui file, so its not gonna work for you. but having you run this code is not the point.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtWidgets import QMainWindow, QApplication, QTreeWidgetItem
from PyQt5 import uic, QtWidgets, Qt #<<flags are not here
from PyQt5 import QtCore
from PyQt5.QtCore import Qt #<<<this is where i found the match flag "MatchExactly"
qtCreatorFile = "Main2.ui" # Enter qt Designer file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class MyApp(QMainWindow):
def __init__(self):
super(MyApp, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.InitModelContentTree()
def InitModelContentTree (self):
modelContentTree = self.ui.ModelContentTree
ThingsItemList = modelContentTree.findItems("Things", Qt.MatchExactly)
ThingsItem = ThingsItemList[0]
QTreeWidgetItem(ThingsItem, ["New Thing"])
print("pause")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
i'm hoping there is a decoder ring, some basic thing i'm missing. i'm proving to be a very bad, very inefficient guesser.
Actually Qt.MatchExactly is in Qt but you must import it in another way:
from PyQt5 import Qt
# ...
ThingsItemList = modelContentTree.findItems("Things", Qt.Qt.MatchExactly)
TL; DR
The Qt submodule is a fake module that allows access to any module such as an alias, for example it is similar to:
from PyQt5 import QtCore as Qt
from PyQt5 import QtGui as Qt
from PyQt5 import QtWidgets as Qt
# ...
# The same for all submodules
For example it can be checked for Qt.MatchExactly:
from PyQt5 import Qt, QtCore
assert(QtCore.Qt.MatchExactly == Qt.Qt.MatchExactly)
So in general the following import:
from PyQt5 import somemodule
somemodule.someclass
It is equivalent to:
from PyQt5 import Qt
Qt.someclass
How to know what submodule a class belongs to?: Well, if you have an IDE that can do a self-report like pycharm, the task is simple since the IDE itself does it. But if I do not have access to the IDE the other option is to use the docs of Qt, for example the docs of Qt::MatchExactly is in this link that in the first part is the following table:
And observe Qt += core so all the elements of that docs belong to the core sub-module of Qt that in PyQt/PySide corresponds to QtCore (in general if the docs of Qt indicate Qt += mymodule in PyQt/PySide in QtMyModule).Also the Qt::MatchExactly of C ++ corresponds to Qt.MatchExactly in python. So in conclusion you should use:
from PyQt5 import QtCore
QtCore.Qt.MatchExactly

Context Menu not displaying correct language with PyQt5

When I was trying to create a Qt application using PyQt5, I noticed that QPlainTextEdit standard context menu was being displayed in English , which is not the language of my system (Portuguese), despite its locale was correctly inherited from its parent widget. Is this the expected behavior? If so, how can i add a translation without having to rewrite the functions already present in that context menu (like cut/copy/paste)?
Example
This program reproduces the behavior described above; it shows a window (thus textEditor.locale().language() have the same value as QLocale.Portuguese) but the context menu is shown in english.
import sys
from PyQt5.QtWidgets import QApplication, QPlainTextEdit, QMainWindow
from PyQt5.QtCore import QLocale
def main():
app = QApplication(sys.argv)
window = QMainWindow()
assert(window.locale().language() == QLocale.Portuguese)
textEditor = QPlainTextEdit(window)
assert(textEditor.locale().language() == QLocale.Portuguese)
window.setCentralWidget(textEditor)
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You need to install a QTranslator to add the translations for your system locale.
import sys
from PyQt5.QtWidgets import QApplication, QPlainTextEdit, QMainWindow
from PyQt5.QtCore import QLocale, QTranslator, QLibraryInfo
def main():
app = QApplication(sys.argv)
# Install provided system translations for current locale
translator = QTranslator()
translator.load('qt_' + QLocale.system().name(), QLibraryInfo.location(QLibraryInfo.TranslationsPath))
app.installTranslator(translator)
window = QMainWindow()
assert(window.locale().language() == QLocale.Portuguese)
textEditor = QPlainTextEdit(window)
assert(textEditor.locale().language() == QLocale.Portuguese)
window.setCentralWidget(textEditor)
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

PyQt5 - Translated texts do not appear in the GUI

Despite existing, translated texts do not appear in my GUI.
Here is the main.py
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow
import sys, os
from view.MainWindow import MainWindow
if __name__=='__main__':
app = QApplication(sys.argv)
mainWindow = MainWindow()
MainWindow.show(mainWindow)
translator = QtCore.QTranslator()
(filepath,filename)=os.path.split(__file__)
trad_path=os.path.join(filepath,'translate','fr_FR.qm')
print (trad_path)
translator.load(trad_path)
app.installTranslator(translator)
sys.exit(app.exec_())
The main.py file is under a src folder alongside a translate folder containing the fr_FR.qm file.
The print (trad_path) shows that the path to the file is correct
Inside , the MainWindow.py file I have a showEvent() function that calls the set_translatable_textes() function
def showEvent(self,ev):
print('in show event')
self.set_translatable_textes()
def set_translatable_textes(self):
self.choose_session_label.setText(
QCoreApplication.translate(
'Main Window','A text that has translation'))
#self.choose_session_label.setText('Untranslated text')
self.edit_button.setText(self.tr('Edit'))
#self.edit_button.setText('Untranslated text')
I try two kinds of translation :
With QCoreApplication.translate()
With tr()
None of them is working. To be sure I call the function, I replace each statements with the commented statement under. They both work.
I am probably doing something wrong but what?
How stupid!
The translator was not ready at the time the MainWindow showed up.
I placed the translator stuff in main before MainWindow.show() and it became fine.

Categories