How to refresh QTableView after an SQL Commit?
-
I went ahead and fixed that duplicate connection issue, although it seems unrelated to my original issue of getting select() to work. I took everything from the databaseSetup class and put it into the Main class so it all happens during the initial setup and I can work with the database from there.
Regarding select(), I think I've narrowed it down to the fact that I seem to be calling the function incorrectly from within a separate class.
Class 1 is the main class where the model lives.
Class 2 is a separate widget class that is part of a second main window (opened via a button). It correctly is able to add to the database, however I can't call
model.select()
on it since that function lives in Class 1.So I guess what I'm asking is, what is the proper way to call that function from within Class 2? I've tried things like
Class1().model.select()
as well as writing a separate method within Class 1 that only doesself.model.select()
and calling it from Class 2 viaClass1().newmethod()
and still no luck. I'm sure it's just me not understanding how to call functions from between classes.If I connect a button within Class 1 to the "new method" for this test case, I should note that it does indeed update as expected.
-
Class1().newmethod()
This created a new object of Class1 and calls the method on it. It does nothing with the actual object you are using.
-
Understood, but what would be the CORRECT way to call that method then? Because when I run it like that, I get
'Class1' object has no attribute 'model'
but if I call it from within Class1 itself, it works, which makes sense if I'm creating a new instance of Class 1 instead of accessing the existing instance.Or if there is a better way of doing what I'm trying to accomplish, what would that be? Could I affect the model directly from the second class somehow?
-
@liquidhamilton said in How to refresh QTableView after an SQL Commit?:
createModel
Until that method is called, your Class1 object has no attribute model since it's created in that method.
You need to give more details. What is Class2, what does it do with respect to Class1 ?
-
Class 1 is the UI_MainWindow class.
Class 2 opens a second window and is essentially an app in its own (scrapes the internet for metadata and then displays it). This class also has a button which creates a new SQL entry with the scraped metadata. All works as expected. However, with respect to Class 1, I need it to triggerself.model.select()
that is created inside Class 1 in order to refresh the TableView on the Class 1 Main Window after the new entry is created.For reference, here is the complete code: https://github.com/LiquidHamilton/Testing/blob/master/libraryApp.py
Line 232 triggers "class 2" to open.
Line 485 is in Class 2 and is where "select()" would need to be called in class 1. -
In that case you should rather use signals and slots. Once your Class2 has finished it job, emit a signal that you will connected to Class1's slot.
-
I've tried that but I get the same errors.
signalTest() missing 1 required positional argument: 'self'
This is really frustrating. All I need to do is call a method, why can't I get this working?class bookSearch(QMainWindow): mysignal = QtCore.pyqtSignal() # methods and whatnot def addClicked(self): self.mysignal.connect(Ui_MainWindow.signalTest()) self.mysignal.emit()
class Ui_MainWindow(QMainWindow): # other methods def signalTest(self): print("signal acquired")
I'm all for learning and figuring things out on my own with minimal assistance, but I've been staring at this same problem for almost 24 hours straight. Could you perhaps tell me exactly how to fix it, so I can work backwards from there and deconstruct it to learn?
-
@liquidhamilton said in How to refresh QTableView after an SQL Commit?:
self.mysignal.connect(Ui_MainWindow.signalTest())
self.mysignal.connect(Ui_MainWindow.signalTest)
, note the omitted()
.And I'm afraid your
Ui_MainWindow
is a class, you would need the instance. And you wouldn't do it this way.I hope someone else can write you a full example of how to connect signals & slots.
-
That just made it click in my head. I was reinitializing the entire class instead of affecting the existing instance of it! I just have no idea how to actually do that haha. I've read the documentation on signals & slots but can't seem to get it to work in this particular instance. Once I understand it, my original question will be solved (because model.select() will be called), and I can apply that knowledge to the additional classes that I'm constructing for this app that need to interact with the first Class, so I appreciate all the help I'm getting.
-
@liquidhamilton
I didn't have time to type more last night. I'm afraid I'm still not offering to type in a whole example, but......There is another wrong in your approach. Although to make the way you have written it could be made to work if you obtain a reference to the main window instance so you can go
self.mysignal.connect(mainUiWindowInstance.signalTest)
you are actually connecting the signal to the slot from the wrong place.
First, just to be clear, when I talk about "the main window" I mean the one of type
Ui_MainWindow
, the one you create as the first thing in your start up code. You have made yourclass bookSearch
[do yourself a favour, make your class names start with an upper-case, make your variables/parameters/methods start with a lower-case, it's much clearer, so this should beclass BookSearch
)] also derive fromQMainWindow
. Although this is allowed because QMainWindow is simply a particular window style suitable for a main window, not a "special" "this is the main window of the app and there can only be one", you almost certainly don't want to do this. Think about organizing so you have just the oneQMainWindow
, if you want to "swap" what is inside it like "pages" put a QStackedWidget inside it. That allows you to define and swap between one given "page" at a time. Or, you might wantBookSearch
to be a modeless QDialog so it sits there all the time and notifies the main window when the user adds a book.That aside, returning to the signal/slot. You have made it so the class which is
emit
ting the signal is responsible for attaching the slot (viaconnect()
) to be called. This is not at all how signals/slots are intended to work! The emitter of a signal does so when it has something to say to the outside world, but it has no knowledge of who is listening to (slotted onto) the signal. It is the places which wish to be notified of the signal to act on it which should connect their slot. That's very important for the logic of signals/slots, it makes the signaller independent of the listeners.Further, you wouldn't
connect()
a signal to a slot when an event happens/just before theemit()
. (Plus, you must not re-connect()
the same signal->slot more than once, i.e. not each time a button is clicked.) You would do it once before any signals get raised, and it remains there for then on.So... in outline you should have:
from booksearch import BookSearch class Ui_MainWindow(QMainWindow): # somewhere when you want to create the BookSearch window self.bookSearch = BookSearch(self) # do the connect() once now # this *instance* of a BookSearch has its signal connected to this *instance* of a Ui_MainWindow's slot self.bookSearch.mySignal.connect(self.signalTest) # somewhere when you want to show it self.bookSearch.show() def signalTest(self): print("signal acquired")
class BookSearch(QWidget): mySignal = QtCore.pyqtSignal() def addClicked(self): self.mySignal.emit()
Note that
BookSearch
, the signaller, does not importUI_MainWindow
and does not need to get the main window instance this way round. It does not know or care about the main window at all, and indeed could be used from elsewhere, and wouldn't care if nobody has a slot on its signal. OTOH,UI_MainWindow
knows thatBookSearch
emitsmySignal
when something happens there, and it connects its slot to that signal from the createdself.bookSearch
instance. -
Wow! I can’t thank you enough for that thorough explanation. That’s exactly what I needed to learn. I’ll be sure to take all of that information and practice on a few smaller examples to help solidify it, and then integrate it into my project.
Edit: I got it to work!! Thank you to everyone who contributed. My understanding of these particular topics has grown substantially!