Results 1 to 2 of 2

Thread: Click Widget button from MainWindow

  1. #1
    Join Date
    Nov 2019
    Posts
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Click Widget button from MainWindow

    Hello Together,

    for the last six hours I tried to click a button on a Widget with a function located in the MainWindow class.

    I also read a lot in several Formus about this Signal Slot concept.
    The best I found is
    https://www.qtcentre.org/threads/498...f-made-widgets

    But even with this I faild to understand the core problem.

    So I if somebody could explain in more detail what to do, could help a lot of people.

    I use the QT basic Example "CAN BUS Example"
    With QT creator 4.10.1 I droped a new pushButton on the surface of the MainWindow.

    Now I simply want to push the "sendbutton" located inside a widget "sendframebox"
    Lets say I want to push the button with a timer like this

    QTimer::singleShot(2000, []{ qDebug("Button "sendButton" located in sendframebox should be pressed");});

    Or a Winwdow function when someting happend...


    My code in MainWindow works like this:


    Qt Code:
    1. void MainWindow::on_radioButton_RUNloop_clicked()
    2. {
    3.  
    4. if(m_ui->Skript_checkbox_send->isChecked())
    5. {
    6. m_ui->sendFrameBox->sendButton_4(); <- HOW TO PUSH THE BUTTON of the widget??
    7. }
    8.  
    9. QTimer::singleShot(2000, []{ qDebug("Or push the button with this singleshot timer");});
    10. }
    To copy to clipboard, switch view to plain text mode 

    Can somebody tell me how to solve this with the signal slots?

    Or how to handle this problem quick and dirty?




    Added after 23 minutes:


    For the other beginners I solved it quick and dirty with public pushButton function.
    But my guess is that it is not really the best solution.

    Here the way I solved it "dirty"

    In the widget *.h locate a public function:

    Qt Code:
    1. public:
    2. ....
    3. void pushSEND4btn();
    4. ...
    To copy to clipboard, switch view to plain text mode 

    In the widget *.cpp locate the wrapper code.
    Qt Code:
    1. void SendFrameBox::pushSEND4btn()
    2. {
    3. m_ui->sendButton_4->click();
    4. }
    To copy to clipboard, switch view to plain text mode 

    Now you can press this button from MainWindow:
    Qt Code:
    1. m_ui->sendFrameBox->pushSEND4btn();
    To copy to clipboard, switch view to plain text mode 

    I hope somebody can tell us the right way to solve such a situation.
    Last edited by rmkeller; 3rd November 2019 at 21:07. Reason: spelling corrections

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,194
    Thanks
    237
    Thanked 668 Times in 658 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Click Widget button from MainWindow

    QPushButton inherits from QAbstractButton. This base class has a slot QAbstractButton::click(). In your pushSEND4btn() method, you are calling this slot as an ordinary function.

    This works, but as you say, it is the "dirty" way to do it, because it exposes internal details of the SendFrameBox class. What happens if you change your UI, and you no longer use a QPushButton or this "SendFrameBox" widget (whatever that is)? Your code would break, because the details of the implementation have changed, and your MainWindow was depending on them.

    The "correct" (i.e. Qt) way is to use signals and slots to communicate between different parts of your program. In your case, one way to do this could be to:

    1 - Implement a signal for your MainWindow class that get emitted when you want to send a message. Call it "sendMessage()" and declare it in your MainWindow.h file in the signals: section.
    2 - Now, you can implement a slot in your MainWindow class that can be called any time you want this signal emitted. Call that slot "doSendMessage()" or something meaningful. So, for example, maybe you have a menu item (Edit -> Send Message), and you have defined the QAction for that menu item. Then, in the MainWindow constructor, you would write:

    Qt Code:
    1. MainWindow::MainWindow( QWidget * parent )
    2. : QMainWindow( parent )
    3. {
    4. // call setupUi(), etc.
    5.  
    6. QAction * pSendAction = new QAction( "Send Message", this );
    7. connect( pSendAction, &QAction::triggered, this, &MainWindow::doSendMessage );
    8.  
    9. // set up the SendFrameBox
    10.  
    11. SendFrameBox * pFrameBox = new SendFrameBox( this );
    12. connect( this, &MainWindow::sendMessage, pFrameBox, &SendFrameBox::handleSendMessage );
    13.  
    14. // do more MainWindow construction
    15. }
    16.  
    17. void MainWindow::doSendMessage()
    18. {
    19. emit sendMessage();
    20. }
    To copy to clipboard, switch view to plain text mode 

    3 - Now, in any class where you want something to happen when MainWindow emits the sendMessage() signal, you can connect a slot to it. This slot can do anything, not just simulate pushing a button. So, for example, in your SendFrameBox widget, you can declare and implement the "handleSendMessage()" slot:

    Qt Code:
    1. void SendFrameBox::handleSendMessage()
    2. {
    3. // do anything you want, like clicking the button
    4. }
    To copy to clipboard, switch view to plain text mode 

    4 - But it would be even better if you could remove the dependence on handling the sendMessage() signal from anything related to a pushbutton or where in the UI that button is found. After all, the pushbutton is simply the way you get your UI to do something on the CAN bus. Again, a Qt way of doing this would be to define a QAction that can be directly connected to whatever method you use to actually send something to the CAN bus.

    Then, the MainWindow sendMessage() signal could be connected to this QAction's trigger() slot. If you have a QPushButton in the SendFrameWidget class, you can connect that button's clicked() signal to the same QAction's trigger() slot. This way, either the MainWindow's menu action -or- the pushbutton click cause exactly the same code to happen - QAction::trigger() slot is called.

    Assuming you have a manager class that directly handles communication with the CAN bus, this class should have a slot that is connected to the QAction::triggered() signal.

    The result is that you have disconnected the process of sending a message to the CAN bus from almost all details of the UI. The only dependence you have are through the QAction, and you can connect its trigger() slot to any UI component you want. You can change the UI to anything, and the only code you have to change is the connection between the UI parts that have changed and the QAction slot.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Replies: 1
    Last Post: 28th July 2019, 03:03
  2. Replies: 4
    Last Post: 11th February 2018, 18:47
  3. Translucent background UI Button click in mainwindow
    By vivekyuvan in forum Qt Programming
    Replies: 0
    Last Post: 19th September 2017, 07:20
  4. Replies: 3
    Last Post: 23rd June 2013, 17:01
  5. "Change widget class on button click" problem
    By utkozanenje in forum Newbie
    Replies: 3
    Last Post: 23rd May 2011, 01:40

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.