I have a QStyledItemDelegate for a table. In one cell I have a QComboBox created through the delegate's createEditor. I add some items to the combobox listing via self.addItem("an item"); however, when I go into the table and actually select the items I have added, they get replaced with index values starting from 0.
How can I have the QComboBox display the actual text I added in addItem instead of the index they're getting stored in?
Here is a small standalone example of my problem:
import sys
from PySide import QtCore, QtGui, QtSql
class EditDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent=None):
super(EditDelegate, self).__init__(parent)
def createEditor(self, parent, option, index):
editor = TheEditor(parent)
return editor
class TheEditor(QtGui.QComboBox):
def __init__(self, parent=None):
super(TheEditor, self).__init__(parent)
self.addItem("Item 1")
self.addItem("Item 2")
self.addItem("Item 3")
self.setEditable(True)
class TheTable(QtGui.QTableWidget):
def __init__(self, columns, parent=None):
super(TheTable, self).__init__(parent)
self.setItemDelegate(EditDelegate())
self.setEditTriggers(QtGui.QAbstractItemView.AllEditTriggers)
self.setColumnCount(1)
self.setRowCount(1)
self.setHorizontalHeaderLabels(["QCombo"])
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setCentralWidget(TheTable(self))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
frame = MainWindow()
frame.show()
app.exec_()
Updating PySide to the latest version resolves the issue.
It seems that the default combobox delegate is messing up with the data it receives.You could have fixed that with a custom delegate to paint the correct data. But since you have already solved it, Congratulations!.
Related
I want to hide a window immediately after it is created. It works only if I do this with the help of button or something.
class Example(QWidget):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self.hide() # doesn't work
self.btn = QPushButton('Hide', self)
self.btn.clicked.connect(self.click) # works
self.btn.show()
def click(self): # works
self.hide()
Apparently it seems that the code should work. What may be happening is that you are calling show() after creating the object. For example:
example = Example()
example.show()
Read this answer about hide() and show(): What's the difference in Qt between setVisible, setShown and show/hide
You can use QtCore.QTimer
class Example(QWidget):
def __init__(self, app):
QWidget.__init__(self)
QTimer.singleShot(0, self.hide)
I created a button in a main window that when clicked will bring up a search window with a tree widget containing rows of data from a MySql database. If I were to open the search window through the .py file on its own it displays the data, but when I open it through the button I programmed, no data is shown. This is the code for the program that runs the main window and creates a button function to open the search window:
from PyQt4 import QtGui
from MainMenu import Ui_MainWindow
from StudentSearch import Ui_Student_search
import DB_manager_students
class MainWindow(Ui_MainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setupUi(self)
self.pushButton_3.clicked.connect(self.handleButton)
self.window2 = None
def handleButton(self):
if self.window2 is None:
self.window2 = Student_search()
self.window2.show()
class Student_search(Ui_Student_search):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
What am I doing wrong? And why is it that it will display the data if I open it by itself, but not when I open it like so?
Edit:
From Student_search.py
class Ui_Student_search(QtGui.QWidget):
def __init__(self, database, tableName):
QtGui.QWidget.__init__(self)
self.dbu = DB_manager_students.DatabaseUtility(database, tableName)
self.setupUi(self)
self.UpdateTree()
(...)
def UpdateTree(self):
col = self.dbu.GetColumns()
table = self.dbu.GetTable()
for c in range(len(col)):
self.StudentTreeWidget.headerItem().setText(c, col[c][0])
self.StudentTreeWidget.clear()
for item in range(len(table)):
QtGui.QTreeWidgetItem(self.StudentTreeWidget)
for value in range(len(table[item])):
self.StudentTreeWidget.topLevelItem(item).setText(value, str(table[item][value]))
Edit:
This is your base widget class
class Ui_Student_search(QtGui.QWidget):
def __init__(self, database, tableName):
QtGui.QWidget.__init__(self)
self.dbu = DB_manager_students.DatabaseUtility(database, tableName)
self.setupUi(self)
self.UpdateTree()
When you instantiate Ui_Student_search(), the Ui_Student_search.__init__() method runs, which creates a database utility, creates the GUI, and runs UpdateTree().
Now, you create a new class -- Student_search -- that inherits from the Ui_Student_search class
class Student_search(Ui_Student_search):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
But when this class is instantiated and Student_search.__init__() is run, it only does half of the things that Ui_Student_search.__init__() was doing. It doesn't create the database manager or update the tree.
What you should be doing is calling the parent class __init__ method so that Ui_Student_search.__init__() can run and do all those things. Also realize that you'll need to pass database and tablename arguments to the Ui_Student_search.__init__ method.
class Student_search(Ui_Student_search):
def __init__(self, database, tablename, parent=None):
Ui_Student_search.__init__(self, parent, database, tablename)
Python has an even simpler syntax to call methods on the base parent class.
class Student_search(Ui_Student_search):
def __init__(self, database, tablename, parent=None):
super(Student_search, self).__init__(parent, database, tablename)
This also means that you'll need to update your MainWindow to feed the necessary contructor arguments to Student_search
def handleButton(self):
if self.window2 is None:
database = '???'
tablename = 'xxx'
self.window2 = Student_search(database, tablename, parent=self)
self.window2.show()
I am new in programming and I have created a simple application with one class in Python and PySide which manipulates phone bill csv files. Now I want an option for mobile too.
How can I add a menubar, when my class inherits from QWidget? Should I write another class which inherits from QMainWindow and then make an instance of my first class as a central widget? Is this the right way to do this?
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
....
class MyWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
widget = MyWidget()
self.setCentralWidget(widget)
...
There's no need for a QMainWindow, you can simply create a QMenuBar in your widget.
class MyWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
self.menu=QtGui.QMenuBar()
self.menu.addAction("do something")
layout=QtGui.QVBoxLayout()
layout.addWidget(self.menu)
A QMainWindow is basically a widget which already has a layout with a menu bar, a toolbar, a status bar, etc. If you don't need all of those functionality, you can use a simple QWidget and add only what you want.
The code below create a simple QTreeWidget with two items one parented to another.
I want the items to be expanded from the begining (so the user doesn't have to click arrow to expand the items):
Here is how it looks by default:
And here is how I would like it to be (expanded: item "C" is visible):
What attribute needs to be set in order for this to work?
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])
class Tree(QtGui.QTreeWidget):
def __init__(self, *args, **kwargs):
super(Tree, self).__init__()
parentItem=QtGui.QTreeWidgetItem('P')
self.addTopLevelItem(parentItem)
childItem=QtGui.QTreeWidgetItem('C')
parentItem.insertChild(0, childItem)
self.show()
tree=Tree()
sys.exit(app.exec_())
You can use QTreeWidget.expandToDepth().
In your case:
from PyQt4 import QtCore, QtGui
app = QtGui.QApplication([])
class Tree(QtGui.QTreeWidget):
def __init__(self, *args, **kwargs):
super(Tree, self).__init__()
parentItem=QtGui.QTreeWidgetItem('P')
self.addTopLevelItem(parentItem)
childItem=QtGui.QTreeWidgetItem('C')
parentItem.insertChild(0, childItem)
self.expandToDepth(0)
self.show()
tree=Tree()
sys.exit(app.exec_())
You could also use expandAll() to expand everything instead of only to certain depth.
I would like to create a widget that has a child widget that I can dynamically change. Here is what I tried:
import sys
from PySide.QtCore import *
from PySide.QtGui import *
class Widget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setLayout(QVBoxLayout())
self.child = QLabel("foo", self)
self.layout().addWidget(self.child)
def update(self):
self.layout().removeWidget(self.child)
self.child = QLabel("bar", self)
self.layout().addWidget(self.child)
app = QApplication(sys.argv)
widget = Widget()
widget.show()
widget.update()
app.exec_()
The problem is that this doesn't actually remove the "foo" label visually. It is still rendered on top of "bar". Screenshot of the problem. How do I remove the old widget so that only the new widget is shown?
I know that I can change the text property of the label. This is not what I want in my application, I need to change the actual widget (to a different widget type).
removeWidget() only removes the item from the layout, it doesn't delete it. You can delete the child widget by calling setParent(None).
def update(self):
self.layout().removeWidget(self.child)
self.child.setParent(None)
self.child = QLabel("bar", self)
self.layout().addWidget(self.child)