PDA

View Full Version : Determine which button was clicked on a different window



dennisvz
2nd December 2019, 22:10
I have an app that has a main window and four sub windows. Let's call the sub windows/modules, A, B, C and D. There are three QPushbuttons each in windows A, B and C (9 total). Each of these nine buttons, when clicked, call the same report function in window D. Depending on which WINDOW sent the click, I want to change some column headings in the report function in window D. I don't really care which of the nine BUTTONS was clicked. It's like I need an "If statement" in the function in window D to determine which Window sent the click. If determining which Window sent the click is not possible, I can still do what I need if I know which BUTTON was clicked.

I've read about Sender() but do not know if this is what I need nor do I know how to code it. Nor do I know C so its hard to follow examples.

Sample code for 3 buttons in one of the windows:


self.ui.WtgAvgPrintBtn.clicked.connect(self.viewst ocks)
self.ui.WtgAvgPrintBtn_2.clicked.connect(self.view stocks)
self.ui.WtgAvgPrintBtn_3.clicked.connect(self.view stocks)


The viewstocks function calls a report function in another window (window D in my example, but it's really called reportsWindow)


def viewstocks(self):
self.reportsWindow.byassetclass()
self.reportsWindow.show()


My questions:
1. What code do I use in widows A, B and C to designate which Window or button was clicked
2. What code in window D do I use to determine which Window or button was clicked,. ie. the "If" statement
3. If I have to go the route of determining which BUTTON was clicked, does it matter if the three button object names in window A are the same as the object names in B and C?
thanks

dennisvz
3rd December 2019, 16:30
RESOLVED: I have decided to simply add two functions (they are small) in the report module -- now there is a unique report for each of the three windows. thanks to all for looking.

d_stranz
3rd December 2019, 21:24
Back to your original post - there is a better way to abstract this than to require your report window to decipher which button in some other, completely unrelated window was the one that was clicked. What happens if you want to add to your UI the ability to change reports based on a menu action or a combobox selection? Your logic to change reports based on button clicks falls apart completely because there is no button.

So what I would do is this:

1 - in your report window, implement a slot that takes as an argument some type of ID - an integer, enum value, string, whatever - that uniquely identifies the report you want to produce

2 - in the windows that hold your buttons, implement slots for each of the button clicked() signals.

3 - in those same windows, implement signals the send an ID value when emitted. In the button click handling slots, emit the signal with the appropriate id value

4 - connect the signals in the button windows to the slot in the report window.

Something like this:



// ButtonWindow.h

signals:
void reportSelected( int reportId );

protected slots:
void onButtonClicked();

// ButtonWindow.cpp

ButtonWindow::ButtonWindow( QWidget * parent )
: // base class constructor
{
ui.setupUi( this );

connect( ui.button, &QPushButton::clicked, this, &ButtonWindow::onButtonClicked );
}

void ButtonWindow::onButtonClicked()
{
emit reportSelected( Report1 ); // "Report1" is a value from an enum, for example
}

// ReportWindow.h

public slots:
void onReportSelected( int reportId );

// ReportWindow.cpp
void ReportWindow::onReportSelected( int reportId )
{
switch reportId:
{
case Report1:
// format a Report1 type report...
break;

// ...
}
}

// MainWindow.cpp

MainWindow::MainWindow( QWidget * parent )
: QMainWindow( parent )
{
ui.setupUi( this );

// create report window
ReportWindow * pRW = new ReportWindow( this );

// create button windows
ButtonWindow * pBW = new ButtonWindow( this );

// connect button window to report window
connect( pBW, &ButtonWindow::reportSelected, pRW, &ReportWindow::onReportSelected );

}


The nice thing about this, even though it uses more signal and slot overhead, is that it completely decouples buttons from reports. The report window doesn't know how the signal to change the report type got generated, all it knows is that it should change the type to whatever was requested. Likewise, the buttons don't know that they are changing a report format, they just know they might be telling something, somewhere, that a new report ID has been chosen.

So this mean you can send a signal with a report ID from anywhere in your UI - a menu, combobox, push button, radio button, whatever - so long as the signal that the control emits is connected to a slot that in turn emits a signal with a report ID. Connect that signal to the report window's slot, and you have added a new capability to your program with no change in the architecture.