Dynamically change translation of application with a combobox with pyqt - python

I'm creating a simple window with a combobox to let user choose the text language to be displayed throughout the app
I have created the necessary .qm files, and the text is being updated when I start the aplication. But how can I link this to the options on the combobox, and change the language dinamically from within the mainWindow?
My code:
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
GUI
'''
import sys
import os.path as osp
import os
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow,self).__init__()
# Set MainWindow geometry, use settings of last session. If it's first session,
# use defaulted settings
self.settings = QtCore.QSettings('Paul',QtCore.QSettings.NativeFormat)
self.resize(self.settings.value("size", QtCore.QSize(500, 300)).toSize())
self.move(self.settings.value("pos", QtCore.QPoint(5, 5)).toPoint());
self.initUI()
def closeEvent(self, e):
#Save MainWindow geometry session when closing the window
self.settings.setValue("size",self.size())
self.settings.setValue("pos",self.pos())
e.accept()
def initUI(self):
self.hbox = QtGui.QVBoxLayout(self) # Create Vertival box layout to put the buttons
self.myButtons = QtGui.QPushButton('button',self) #create push button
self.myButtons.setStyleSheet("""QPushButton { background-color: red; font:bold 20px}""")
self.myButtons.setToolTip('Push this button')
self.myButtons.setText(self.tr('yes'))
comboBox=QtGui.QComboBox(self) #create drop down menu
comboBox.addItem('English')
comboBox.addItem('Portugues')
self.hbox.addWidget(comboBox,1,QtCore.Qt.AlignRight) #add drop down menu to box layout
self.hbox.addStretch(3) # set separation between buttons
self.hbox.addWidget(self.myButtons,1,QtCore.Qt.AlignRight) #add button to box layout
self.setWindowTitle('Test2')
self.show()
def main():
app = QtGui.QApplication(sys.argv)
translator = QtCore.QTranslator()
translator.load("~/translations/qt_pt.qm")
app.installTranslator(translator)
app.setWindowIcon(QtGui.QIcon(path))
ex = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Basically I would like to have the combobox do something like this:
self.comboBox.currentIndexChanged.connect(self.combochange)
def combochange(self):
if self.comboBox.currentText()=='Portugues':
translator = QtCore.QTranslator()
translator.load('~/translations/qt_pt.qm')
app.installTranslator(translator) #Obviously this doesn't work
I assume I have to somehow pass an argument from the mainWindow to the main() function and reload everything.
Is this even possible?
Python 2.7, QT 5.9.1, PyQt4 4.12.1 on OSX 10.11.6
EDIT:
I found this post on QT wiki page that does what I want, unfortunately I am not proficient in C, at all. If someone could help me translate this to python I would be greatly appreciated.

Here is a more appropriated way to do it:
#create a new translator and load the desired translation file
translator = QtCore.QTranslator()
translator.load("monAppli_fr.qm")
#install translator to the app
#app is the variable created in (if __name__ == "__main__":) section, make it gloabl
app.installTranslator(translator)
#call retranslateUi on ui, which is defined in the same section as app
#MainWindow : created in the same section
ui.retranslateUi(MainWindow)
That's it, and my if __name__ == '__main__': section looks like :
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

Ok, I found a way to do it, I don't know if it is a very "pythonic" solution, but it works
my main() function now looks like this:
if __name__ == '__main__':
lang =1 #default language
i=0
while i>=0:
i=i+1
if lang == 1:
print "i'm english"
if i>1:
app2=None # to erase the previous aplication when we loop between two language choices
app = QtGui.QApplication(sys.argv)
translator = QtCore.QTranslator()
translator.load("~/translations/qt_pt.qm")
app.removeTranslator(translator)
ex = MainWindow(lang)
ex.show()
lang =app.exec_()
elif lang==0:
print "i'm portuguese"
app=None
app2 = QtGui.QApplication(sys.argv)
translator = QtCore.QTranslator()
translator.load("~/translations/qt_pt.qm")
app2.installTranslator(translator)
ex = MainWindow(lang)
ex.show()
lang=app2.exec_()
print "im here"
To now which language my aplication needs to load, following user input in the combobox I defined my "combochange" function like so:
def combochange(self,e):
#print self.comboBox.currentText()
if self.comboBox.currentText()=="Portugues":
MainWindow.lang=0
QtGui.qApp.exit(MainWindow.lang)
else:
MainWindow.lang=1
QtGui.qApp.exit(MainWindow.lang)
"lang" is passed outside my mainWindow, which triggers one application to close and be reopened with a different language.
It doesn't look very elegant, but it works.
The full code is:
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
GUI
'''
import sys
import os.path as osp
import os
from PyQt4 import QtGui, QtCore
class MainWindow(QtGui.QWidget):
def __init__(self,lang2):
super(MainWindow,self).__init__()
# Set MainWindow geometry, use settings of last session. If it's first session,
# use defaulted settings
self.settings = QtCore.QSettings('Paul',QtCore.QSettings.NativeFormat)
self.resize(self.settings.value("size", QtCore.QSize(500, 300)).toSize())
self.move(self.settings.value("pos", QtCore.QPoint(5, 5)).toPoint());
self.initUI(lang2)
def closeEvent(self, e):
#Save MainWindow geometry session when closing the window
self.settings.setValue("size",self.size())
self.settings.setValue("pos",self.pos())
e.accept()
sys.exit()
def initUI(self,lang2):
self.hbox = QtGui.QVBoxLayout(self) # Create Vertival box layout to put the buttons
self.myButtons = QtGui.QPushButton('button',self) #create push button
self.myButtons.setStyleSheet("""QPushButton { background-color: red; font:bold 20px}""")
self.myButtons.setToolTip('Push this button')
#self.myButtons.setText(QtCore.QString(self.tr('yes')))
self.myButtons.setText(self.tr("yes"))
self.comboBox=QtGui.QComboBox(self) #create drop down menu
if lang2 == 1:
self.comboBox.addItem('English')
self.comboBox.addItem('Portugues')
else:
self.comboBox.addItem('Portugues')
self.comboBox.addItem('English')
self.comboBox.currentIndexChanged.connect(self.combochange)
self.hbox.addWidget(self.comboBox,1,QtCore.Qt.AlignRight) #add drop down menu to box layout
self.hbox.addStretch(3) # set separation between buttons
self.myButtons.clicked.connect(self.buttonClicked) # what should the button do
self.hbox.addWidget(self.myButtons,1,QtCore.Qt.AlignRight) #add button to box layout
self.setWindowTitle('Test2')
def combochange(self,e):
#print self.comboBox.currentText()
if self.comboBox.currentText()=="Portugues":
MainWindow.lang=0
QtGui.qApp.exit(MainWindow.lang)
else:
MainWindow.lang=1
QtGui.qApp.exit(MainWindow.lang)
def buttonClicked(self):
msbox= QtGui.QMessageBox()
choice=msbox.warning(self,'ok',"This button doesn't do anything!!!")
if choice == QtGui.QMessageBox.No:
print('nanan')
else:
print('Bye')
self.settings.setValue("size",self.size());
self.settings.setValue("pos",self.pos());
sys.exit()
if __name__ == '__main__':
lang =1
i=0
while i>=0:
i=i+1
print i
if lang == 1:
print "i'm english"
if i>1:
app2=None
app = QtGui.QApplication(sys.argv)
translator = QtCore.QTranslator()
translator.load("/Users/paulmota/Documents/BlueBerryProject/basefiles/translations/qt_pt.qm")
app.removeTranslator(translator)
ex = MainWindow(lang)
ex.show()
lang =app.exec_()
elif lang==0:
print "i'm portuguese"
app=None
app2 = QtGui.QApplication(sys.argv)
translator = QtCore.QTranslator()
translator.load("/Users/paulmota/Documents/BlueBerryProject/basefiles/translations/qt_pt.qm")
app2.installTranslator(translator)
ex = MainWindow(lang)
ex.show()
lang=app2.exec_()
print "im here"

Related

QFileDialog.getOpenFileName change button text from 'Open' to 'Remove'

I am using QFileDialog.getOpenFileName(self,'Remove File', "path", '*.pdf') to select a file and get the path in order to remove it from my application. The issue is the QFileDialog.getOpenFileName window button says 'Open' when selecting a file which will be confusing to the user.
Is there any way to change the button text from 'Open' to 'Remove'/'Delete'
When using the static method QFileDialog::getOpenFileName() the first thing is to obtain the QFileDialog object and for that we use a QTimer and the findChild() method:
# ...
QtCore.QTimer.singleShot(0, self.on_timeout)
filename, _ = QtWidgets.QFileDialog.getOpenFileName(...,
options=QtWidgets.QFileDialog.DontUseNativeDialog)
def on_timeout(self):
dialog = self.findChild(QtWidgets.QFileDialog)
# ...
Then you can get the text iterating over the buttons until you get the button with the searched text and change it:
for btn in dialog.findChildren(QtWidgets.QPushButton):
if btn.text() == "&Open":
btn.setText("Remove")
That will work at the beginning but every time you interact with the QTreeView they show, update the text to the default value, so the same logic will have to be applied using the currentChanged signal from the selectionModel() of the QTreeView but for synchronization reasons it is necessary Update the text later using another QTimer.singleShot(), the following code is a workable example:
import sys
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button = QtWidgets.QPushButton("Press me")
button.clicked.connect(self.on_clicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(button)
#QtCore.pyqtSlot()
def on_clicked(self):
QtCore.QTimer.singleShot(0, self.on_timeout)
filename, _ = QtWidgets.QFileDialog.getOpenFileName(
self,
"Remove File",
"path",
"*.pdf",
options=QtWidgets.QFileDialog.DontUseNativeDialog,
)
def on_timeout(self):
dialog = self.findChild(QtWidgets.QFileDialog)
dialog.findChild(QtWidgets.QTreeView).selectionModel().currentChanged.connect(
lambda: self.change_button_name(dialog)
)
self.change_button_name(dialog)
def change_button_name(self, dialog):
for btn in dialog.findChildren(QtWidgets.QPushButton):
if btn.text() == self.tr("&Open"):
QtCore.QTimer.singleShot(0, lambda btn=btn: btn.setText("Remove"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
The first step can be avoided if the static method is not used and create the dialog using an instance of QFileDialog:
import sys
from PyQt5 import QtCore, QtWidgets
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
button = QtWidgets.QPushButton("Press me")
button.clicked.connect(self.on_clicked)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(button)
#QtCore.pyqtSlot()
def on_clicked(self):
dialog = QtWidgets.QFileDialog(
self,
"Remove File",
"path",
"*.pdf",
supportedSchemes=["file"],
options=QtWidgets.QFileDialog.DontUseNativeDialog,
)
self.change_button_name(dialog)
dialog.findChild(QtWidgets.QTreeView).selectionModel().currentChanged.connect(
lambda: self.change_button_name(dialog)
)
if dialog.exec_() == QtWidgets.QDialog.Accepted:
filename = dialog.selectedUrls()[0]
print(filename)
def change_button_name(self, dialog):
for btn in dialog.findChildren(QtWidgets.QPushButton):
if btn.text() == self.tr("&Open"):
QtCore.QTimer.singleShot(0, lambda btn=btn: btn.setText("Remove"))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
While I appreciate the solution provided by #eyllanesc, I'd like to propose a variation.
Under certain circumstances, the code for that answer might fail, specifically:
the delay that X11 suffers from mapping windows;
the checking of localized button strings;
the selection using the file name edit box;
Considering the above, I propose an alternate solution, based on the points above.
For obvious reasons, the main point remains: the dialog must be non-native.
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class FileDialogTest(QWidget):
def __init__(self):
super().__init__()
layout = QHBoxLayout(self)
self.fileEdit = QLineEdit()
layout.addWidget(self.fileEdit)
self.selectBtn = QToolButton(icon=QIcon.fromTheme('folder'), text='…')
layout.addWidget(self.selectBtn)
self.selectBtn.clicked.connect(self.showSelectDialog)
def checkSelectDialog(self):
dialog = self.findChild(QFileDialog)
if not dialog.isVisible():
# wait for dialog finalization, as testOption might fail
return
# dialog found, stop the timer and delete it
self.sender().stop()
self.sender().deleteLater()
if not dialog.testOption(dialog.DontUseNativeDialog):
# native dialog, we cannot do anything!
return
def updateOpenButton():
selection = tree.selectionModel().selectedIndexes()
if selection and not tree.model().isDir(selection[0]):
# it's a file, change the button text
button.setText('Select my precious file')
tree = dialog.findChild(QTreeView)
button = dialog.findChild(QDialogButtonBox).button(
QDialogButtonBox.Open)
# check for selected files on open
updateOpenButton()
# connect the selection update signal
tree.selectionModel().selectionChanged.connect(
lambda: QTimer.singleShot(0, updateOpenButton))
def showSelectDialog(self):
QTimer(self, interval=10, timeout=self.checkSelectDialog).start()
path, filter = QFileDialog.getOpenFileName(self,
'Select file', '<path_to_file>',
"All Files (*);;Python Files (*.py);; PNG Files (*.png)",
options=QFileDialog.DontUseNativeDialog)
if path:
self.fileEdit.setText(path)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
ex = FileDialogTest()
ex.show()
sys.exit(app.exec())
Obviously, for PyQt6 you'll need to use the proper Enum namespaces (i.e. QFileDialog.Option.DontUseNativeDialog, etc.).

How can I make the menubar in PyQt5 have initial focus?

I have created a GUI with a menubar. However, when I run the app and the window opens I want to be able to iterate through the buttons using only the keyboard. This works for the buttons and lineedit fields, but does not work for the MenuBar.
How can I be able to get focus on the MenuBar such that I can iterate through the actions in the menubar using only the keyboard?
from PyQt5 import QtCore, QtWidgets, QtGui
class ConfigNumbers(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setupUi ( self)
self.setWindowTitle ( 'Nr configs' )
def setupUi(self, ConfigNumbers):
ConfigNumbers.setEnabled ( True )
ConfigNumbers.setFocusPolicy ( QtCore.Qt.TabFocus )
layout = QtWidgets.QGridLayout()
#ELEMENTS
#ACTIONS TO MENUBAR
self.menuBar = QtWidgets.QMenuBar()
delete = self.menuBar.addMenu("Delete")
add = self.menuBar.addMenu("Add")
deleteNr = []
addNr = QtWidgets.QAction("Add New Master", self)
addNr.setShortcut("Ctrl+A")
# addNr.triggered.connect(lambda: self.addNewNr())
add.addAction(addNr)
for nr in range (1,5):
deleteNr.append(QtWidgets.QAction("Nr %d" % nr, self))
delete.addAction(deleteNr[nr-1])
QtCore.QTimer.singleShot(0, self.menuBar.setFocus)
layout.addWidget(self.menuBar)
layout.addWidget(QtWidgets.QPushButton("push"))
self.setLayout( layout )
def main():
app = QtWidgets.QApplication(sys.argv)
window = ConfigNumbers()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You don't need to focus the menu to be able to select it with the keyboard, you can select it by using the key Alt which is the standard key to achieve this, furthermore, you can add the ampersand character before a letter to your menu action titles and then you can use the combination of Alt+letter to access a menu, for example:
import sys
from PyQt5 import QtCore, QtWidgets, QtGui
class ConfigNumbers(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.setupUi ( self)
self.setWindowTitle ( 'Nr configs' )
def setupUi(self, ConfigNumbers):
ConfigNumbers.setEnabled ( True )
ConfigNumbers.setFocusPolicy ( QtCore.Qt.TabFocus )
layout = QtWidgets.QGridLayout()
#ELEMENTS
#ACTIONS TO MENUBAR
self.menuBar = QtWidgets.QMenuBar()
delete = self.menuBar.addMenu("Dele&te")
add = self.menuBar.addMenu("&Add")
deleteNr = []
addNr = QtWidgets.QAction("Add New &Master", self)
addNr.setShortcut("Ctrl+A")
# addNr.triggered.connect(lambda: self.addNewNr())
add.addAction(addNr)
for nr in range (1,5):
deleteNr.append(QtWidgets.QAction("Nr %d" % nr, self))
delete.addAction(deleteNr[nr-1])
layout.addWidget(self.menuBar)
layout.addWidget(QtWidgets.QPushButton("push"))
self.setLayout( layout )
def main():
app = QtWidgets.QApplication(sys.argv)
window = ConfigNumbers()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Now when I hit and release the key Alt I can see the following:
Now you can use the arrow keys to move through the menus; If I hit Alt+A it opens the "Add" menu and so on...
You should also avoid focusing on items using a timer as it may interact with user actions in the interface.

Text from QLineEdit not displaying

I am grabbing the user input from the line edit and displaying it on the QMessageBox but it won't show for some reason. I thought maybe I wasn't grabbing the input from QLineEdit at all but when I tried printing it on the terminal (it still wouldn't show there btw) the terminal scrolled down, recognizing that there is new data in it but just not displaying it. Get what I am saying?
import os
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
def main():
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
class MyWindow(QWidget):
def __init__(self, *args):
QWidget.__init__(self, *args)
# create objects
label = QLabel(self.tr("enter the data "))
self.le = QLineEdit()
self.te = QTextEdit()
# layout
layout = QVBoxLayout(self)
layout.addWidget(label)
layout.addWidget(self.le)
layout.addWidget(self.te)
self.setLayout(layout)
# create connection
self.mytext = str(self.le.text())
self.connect(self.le, SIGNAL("returnPressed(void)"),
self.display)
def display(self):
QApplication.instance().processEvents()
msg = QMessageBox.about(self, 'msg', '%s' % self.mytext)
print(self.mytext)
self.te.append(self.mytext)
self.le.setText("")
if __name__ == "__main__":
main()
You are currently reading the QLineEdit in the constructor, and at that moment the QLineEdit is empty, you must do it in the slot:
def display(self):
mytext = self.le.text()
msg = QMessageBox.about(self, 'msg', '%s' % mytext)
self.te.append(mytext)
self.le.clear()
Note: use clear() to clean the QLineEdit

Python and QsystemTray application

I have a code which runs on KDE system very well.
On Unity (Ubuntu 16.04 LTS) this code produces unexpected result.
Result on Unity:
wrong result on Unity
Bus the same code produces good result on KDE system:
Link to a good result
Question: Why the same code does not work on Unity?
And a code:
import sys
from PyQt4 import QtGui
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtGui.QMenu(parent)
edit = QtGui.QLineEdit(parent)
edit.setText("Tekstas kuris turi būti atsiradęs čia")
hl = QtGui.QVBoxLayout(parent)
hl.addWidget(QtGui.QLabel("Testuojame"))
hl.addWidget(edit)
w = QtGui.QWidget(parent)
w.setLayout(hl)
wa = QtGui.QWidgetAction(parent)
wa.setDefaultWidget(w)
menu.addAction(wa)
exitAction = menu.addAction("Blabla")
exitAction = menu.addAction("Blabla 2")
self.setContextMenu(menu)
def main():
app = QtGui.QApplication(sys.argv)
w = QtGui.QWidget()
trayIcon = SystemTrayIcon(QtGui.QIcon("icons/close.png"), w)
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I see the same behaviour on KDE 5.26.0 (Qt 5.6.1, Ubuntu 16.10), the defaultWidget is not shown in the context menu, only the (empty) iconText of the QWidgetAction is displayed. The way the context menu is shown is ultimately controlled by the tray (which is specific to the used desktop environment).
To get this to work consitently you can show your menu as a popup menu on activation instead of in the context menu. The difference is that it isn't activated on right click but on left click and that it may look different from the native trays context menu.
Your example would then look like this:
import sys
from PyQt4 import QtGui
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
self.menu = menu = QtGui.QMenu()
edit = QtGui.QLineEdit()
edit.setText("Tekstas kuris turi būti atsiradęs čia")
w = QtGui.QWidget()
hl = QtGui.QVBoxLayout()
w.setLayout(hl)
hl.addWidget(QtGui.QLabel("Testuojame"))
hl.addWidget(edit)
wa = QtGui.QWidgetAction(menu)
wa.setDefaultWidget(w)
menu.addAction(wa)
exitAction = menu.addAction("Blabla")
exitAction = menu.addAction("Blabla 2")
self.activated.connect(self.showPopupMenu)
def showPopupMenu(self, reason):
if reason == QtGui.QSystemTrayIcon.Trigger:
self.menu.popup(QtGui.QCursor.pos())
def main():
app = QtGui.QApplication(sys.argv)
trayIcon = SystemTrayIcon(QtGui.QIcon("icons/close.png"))
trayIcon.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Python: PyQt QTreeview example - selection

I'm using Python 2.7 and Qt designer and I'm new to MVC:
I have a View completed within Qt to give me a directory tree list, and the controller in place to run things. My question is:
Given a Qtree view, how may I obtain a directory once a dir is selected?
Code snap shot is below, I suspect it's SIGNAL(..) though I'm unsure:
class Main(QtGui.QMainWindow):
plot = pyqtSignal()
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
# create model
model = QtGui.QFileSystemModel()
model.setRootPath( QtCore.QDir.currentPath() )
# set the model
self.ui.treeView.setModel(model)
**QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked()'), self.test)**
def test(self):
print "hello!"
The signal you're looking for is selectionChanged emmited by the selectionModel owned by your tree. This signal is emmited with the selected item as first argument and the deselected as second, both are instances of QItemSelection.
So you might want to change the line:
QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked()'), self.test)
to
QtCore.QObject.connect(self.ui.treeView.selectionModel(), QtCore.SIGNAL('selectionChanged()'), self.test)
Also I recommend you to use the new style for signals and slots. Redefine your test function as:
#QtCore.pyqtSlot("QItemSelection, QItemSelection")
def test(self, selected, deselected):
print("hello!")
print(selected)
print(deselected)
Here you have a working example:
from PyQt4 import QtGui
from PyQt4 import QtCore
class Main(QtGui.QTreeView):
def __init__(self):
QtGui.QTreeView.__init__(self)
model = QtGui.QFileSystemModel()
model.setRootPath( QtCore.QDir.currentPath() )
self.setModel(model)
QtCore.QObject.connect(self.selectionModel(), QtCore.SIGNAL('selectionChanged(QItemSelection, QItemSelection)'), self.test)
#QtCore.pyqtSlot("QItemSelection, QItemSelection")
def test(self, selected, deselected):
print("hello!")
print(selected)
print(deselected)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
PyQt5
In PyQt5 is a little bit different (thanks to Carel and saldenisov for comments and aswer.)
... connect moved from being an object method to a method acting upon the attribute when PyQt went from 4 to 5
So instead the known:
QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked()'), self.test)
now you write:
class Main(QTreeView):
def __init__(self):
# ...
self.setModel(model)
self.doubleClicked.connect(self.test) # Note that the the signal is now a attribute of the widget.
Here is a the example (by saldenisov) using PyQt5.
from PyQt5.QtWidgets import QTreeView,QFileSystemModel,QApplication
class Main(QTreeView):
def __init__(self):
QTreeView.__init__(self)
model = QFileSystemModel()
model.setRootPath('C:\\')
self.setModel(model)
self.doubleClicked.connect(self.test)
def test(self, signal):
file_path=self.model().filePath(signal)
print(file_path)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
In PyQt5 it can be done in this way:
from PyQt5.QtWidgets import QTreeView,QFileSystemModel,QApplication
class Main(QTreeView):
def __init__(self):
QTreeView.__init__(self)
model = QFileSystemModel()
model.setRootPath('C:\\')
self.setModel(model)
self.doubleClicked.connect(self.test)
def test(self, signal):
file_path=self.model().filePath(signal)
print(file_path)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
If I understand the question correctly you would like the directory or file name selected.
This is what I do:
from PyQt4 import QtGui
from PyQt4 import QtCore
# ---------------------------------------------------------------------
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(600,400)
self.setWindowTitle("Treeview Example")
self.treeview = QtGui.QTreeView(self)
self.treeview.model = QtGui.QFileSystemModel()
self.treeview.model.setRootPath( QtCore.QDir.currentPath() )
self.treeview.setModel(self.treeview.model)
self.treeview.setColumnWidth(0, 200)
self.setCentralWidget(self.treeview)
self.treeview.clicked.connect(self.on_treeview_clicked)
# ---------------------------------------------------------------------
#QtCore.pyqtSlot(QtCore.QModelIndex)
def on_treeview_clicked(self, index):
indexItem = self.treeview.model.index(index.row(), 0, index.parent())
# path or filename selected
fileName = self.treeview.model.fileName(indexItem)
# full path/filename selected
filePath = self.treeview.model.filePath(indexItem)
print(fileName)
print(filePath)
# ---------------------------------------------------------------------
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
I tried this alternative to get the file name...
Instead of:
indexItem = self.treeview.model.index(index.row(), 0, index.parent())
# path or filename selected
fileName = self.treeview.model.fileName(indexItem)
I tried:
# path or filename selected
fileName = index.internalPointer().fileName
Which also seems to work...

Categories

Resources