I've tried virtually every way possible to hook the activated() signal of a taskbar icon to a corresponding slot. However, I do not understand why Qt(Qt5 Cretor) says I don't have a matching function for the slot.
Qt Error:
C:\Users\potato\Desktop\CCT-master\CCTracker\cctsystemtray.cpp:40:
error: no matching function for call to
'QObject::connect(QSystemTrayIcon*&, const char*, CCTSystemTray*
const, const char*)'this,
SLOT(systrayActivated(QSystemTrayIcon::ActivationReason)))
As far as I can tell, according to Qt Documentation,
The activated() signal is used to catch mouse events such as clicks and double clicks for the taskbar icon. At first try I thought it's only signals and slots, but then for whatever reason activated() just won't fit. And If I try connecting activated() to a slot from another class, everything fails due to pointer errors.
Here's are the working parts inside CCTSystemTray.h:
class CCTSystemTray
{
public:
CCTSystemTray();
void initSystemTray(QWidget *rootWindow);
private:
QSystemTrayIcon* systray;
public slots:
void systrayActivated(QSystemTrayIcon::ActivationReason);
};
And CCTSystemTray.cpp:
// Above are Class declearations, menu items, etc...
QObject::connect(this->systray, SIGNAL(QSystemTrayIcon::activated(QSystemTrayIcon::ActivationReason reason)),
this, SLOT(systrayActivated(QSystemTrayIcon::ActivationReason)));
}
void CCTSystemTray::systrayActivated(QSystemTrayIcon::ActivationReason)
{
qDebug() << "Hello";
}
The full code sample can be found here on pastebin.
If someone can help me out from hair-pulling, that'd be great!
Thank you all.
Your class CCTSystemTray has a slot, but it is not a QObject (it doesn't derive from QObject or another class derived from QObject) and also you need the Q_OBJECT macro in your class declaration and then signals and slots will work.
Related
I already finished the implementation I wanted, but I was wondering if this is the right way. I'm confused about the 'is-a' relationship in inheritance.
Background:
I wanted to put a QStackedWidget with four widget pages in the main window.
However, as I implemented it, I realized that I need common functions of pages, such as moving to the next or previous or first page, or moving to the first page when a timeout is triggered after a certain period of time. So I decided to create a parent widget from which my custom widget would inherit.
So, my code like:
// pageWidget.h
// this parent class has no UI
class pageWidget : public QWidget {
Q_OBJECT;
public:
pageWidget(int timeout, QWidget *parent = nullptr); // set the first parameter to the timer
signals:
void goNext();
void goPrev();
void goHome();
private:
// emit goHome() when this timer triggered, start in `showEvent()`, stop in `hideEvent()`
QTimer *timer;
}
// pageOne.h
// this child class has UI with some buttons
// and connected the clicked signal of the buttons to the signal such as `goNext()`.
class pageOne : public pageWidget{
Q_OBJECT;
}
// mainWindow.cpp
mainWindow::mainWindow(...)
{
...
connect(ui->page_1, &pageWidget::goNext, this, &mainWindow::onGoNext);
connect(ui->page_2, &pageWidget::goPrev, this, &mainWindow::onGoPrev);
// other signals such as `goPrev()` and other pages are connected same way.
}
void mainWindow::onGoPrev()
{
ui->stackedWidget->setCurrentIndex(ui->stackedWidget->currentIndex() - 1);
}
It works fine. However, when the goPrev() signal is received on the first page(index 0), currentIndex() - 1 is called (meaning the index is set to -1), but QStackedWidget ignores it, so nothing happens. But it doesn't make any sense, it's rather unnecessary behavior, so I shouldn't do it. Therefore, the goPrev() signal on the first page is not connected, and there is no button for it.
The same goes for the timer that returns to the first page when time elapses. If the time received as an parameter in the constructor of the parent class is 0, the timer is not started, and the first page passes 0.
So the child class(pageOne) 'can' work like the parent class(pageWiget) if desired, but it is also true that some features of the parent class are missing. Of course, just because I don't click a button doesn't mean it isn't a button. But if ​button that never clicks, it's a label or something else. And it feels like 'I can do this, but I should not' rather than 'I can do this but I don't use it'. It's like using an array to implement a set that doesn't allow duplicates.
So, Finally, here's my question :
Is this still an 'is-a' relationship? Is public inheritance the right way?
I think this was a stupid question. My thoughts after sleeping for a while is that the behavior of the pageWidget is until it emits a signal, and all page can behavior whether it's the first page or the last page. Whether to use the emitted signal or not is an entirely different matter. Next time I'll sleep a bit more and think again so I don't ask stupid questions.
I am new to Qt and trying to implement what should be a pretty straightforward "key pressed" event method, but it doesn't seem to be registering properly.
Here is the declaration in my header file:
#include <Qt>
#include <QKeyEvent>
class MainWindow : public QMainWindow
{
Q_OBJECT
protected:
void KeyPressEvent(QKeyEvent* event);
};
and here is the implementation:
void MainWindow::KeyPressEvent(QKeyEvent *event)
{
qDebug() << "Registered Key Press";
}
This is almost exactly what the examples I have seen online look like, so unless there is some connection somewhere I am missing, not sure what the issue would be.
It is, as you say, almost exactly what the examples show. They should show
void keyPressEvent(QKeyEvent* event) override;
See QWidget::keyPressEvent. Note that C++ is case sensitive (K -> k).
Also, I've added the override keyword - then the compiler will tell you if you try to override a function which the compiler doesn't know!
Additional caveats are included in above linked documentation:
Make sure to call setFocusPolicy with an appropriate policy;
Note also that child widgets can "swallow" events. Meaning that if your main window has any children; and the key press happens inside a child, the child can say "I handle this event, no need to pass it on to my parent". Then your MainWindow::keyPressEvent also won't get called; see the corresponding notes in the QKeyEvent documentation; the gist: any child window of your MainWindow handling keyPressEvent has to ignore() the event in order for it to propagate to the parent class.
I have looked at a variety of the Qt discussions for this error "no matching function for call to" and I still cannot see what is different in this case. I have successfully set up slot/signal pairs between GUI elements, but for some reason the latest set of slot/signal pairs is creating an error.
In order to allow all GUI elements to update the status bar on the main window I have created a signal in each panel as shown here
class PanelA : public QWidget
{
...
public signals:
void UpdateStatusBar(std::string);
...
}
Then in MainWindow there is a slot
//from MainWindow.h
class MainWindow : public QMainWindow
{
private slots:
void ReceiveStatus(std::string);
}
//from MainWindow.cpp
void MainWindow::ReceiveStatus(std::string s)
{
//I can provide other controls, filters, etc.
//but currently there are none
ui->statusBar->showMessage(tr("System status: "+s));
}
And finally, in the MainWindow constructor I have several signals already and I have added one new connect line for each GUI element.
connect(ui->panelA, &PanelA::SelectionChanged, ui->panelB, &PanelB::UpdateSelection);
//this one works
connect(ui->panelA, &PanelA::UpdateStatusBar, ui, &MainWindow::ReceiveStatus);
//this one generates an error there is one status bar connection for each
So, as far as I can tell the syntax is right. both ui->panelA and ui are pointers. I don't know why one is correct and the other is wrong. I'd appreciate any suggestions.
Probably should be:
connect(ui->panelA, &PanelA::UpdateStatusBar, this, &MainWindow::ReceiveStatus);
The ui object isn't a MainWindow, but this will be.
In Qt C++, I have a parent object MainWindow. MainWindow has (among others) 2 member objects: vector, and Serial.
Some relevant members of GUI:
QPushButton pushButton;
int itemNumber;
Relevant members of Serial:
void send(int number)
When GUI's member pushButton is clicked, I want to pass GUI's member 'pushButton' as the argument to the function Serial::send(int number). I see one option of doing something like
connect(GUI,SIGNAL(clicked()),this,SLOT(customSlot()));
in my MainWindow function. However, then I don't know which item in my vector it came from, so I don't know which itemNumber to grab (they're all different).
I also thought maybe I'd do it in the GUI class, but that doesn't have access to the Serial::send(int number) method. I don't want a Serial object in each GUI, because it just won't work that way at this point.
How can I pass information from the child object GUI up to the parent object MainWindow from a signal?
Thanks!
Use QObject::sender() function inside a slot to get the object witch sent a signal.
Of course, you need some appropriate cast method:
void someSlot() {
QPushButton *sender = qobject_cast<QPushButton *>(sender());
...
}
i am new to QT and was trying to create a custom signal that would tell me a removable disk has been inserted.
This is what i did
MainWindow.h
class MainWindow
{
QOBJECT
..
..
signals:
void qm_diskInserted(QString &);
public slots:
void addItemToList(QString &);
...
}
MainWindow.cpp
void MainWindow::onDeviceChange(MSG * msg)
{
//code for detecting device here
QString &driveLetter= getDriveLetter(mask);
//try to emit QT signal here
emit qm_diskInserted(driveLetter);
}
MainWindow::MainWindow(QWidget * parent=NULL)
{
ui.setupUi(this);
QObject::connect(this, SIGNAL(qm_diskInserted(QString&)), this, SLOT(addItemToList(QString &));
}
void MainWindow::addItemToList(QString &)
{
//more stuff here
}
somehow the slot addItemToList() isn't called and i have to call it manually.
What am i doing wrong?
Thanks.
PS:
By the way is there any way of debugging signals?
Ie how can i be sure that a signal is emitted?
It is at least supposed to be Q_OBJECT. I think you also need to inherit QMainWindow.
This is a long shot, but are you sure onDeviceChange() method is called?
EDIT
Classes which have Q_OBJECT macro in their body needs to inherit directly or indirectly from QObject, and in your code it is not the case.
With connection problems, always make sure that you check the console for messages about connect failures. Since Qt can't tell if a connection makes sense until runtime, it notifies you of failures there. You'd think it would crash, but it just quietly says these things in the console.
With Qt, it makes sense to watch the console always. Qt prints out all sorts of error messages that can help when you've got a problem.
Try making your signals virtual void instead and make sure that your MainWindow class inherits (directly or indirectly) from QObject
EDIT
As mentioned in other comments, the macro should be Q_OBJECT