My implementation of QTabWidget is not detecting its tabCloseRequested() and currentChanged() signals.
TileSheetManager::TileSheetManager(QWidget *parent)
: QTabWidget(parent)
{
int w = WIDTH;
int h = HEIGHT;
this->setMinimumSize(w, h);
this->setMaximumSize(w, h);
setTabsClosable(true);
setTabShape(QTabWidget::Rounded);
connect(this, SIGNAL(tabCloseRequested(int index)), this, SLOT(closeTileWidget(int index)));
connect(this, SIGNAL(currentChanged(int index)), this, SLOT(tabChanged(int index)));
}
qDebug() was not working for me, so I'm using a QMessageBox for this.
void TileSheetManager::closeTileWidget(int index)
{
QMessageBox msgBox;
msgBox.setText("Tab " + QString::number(index) + " removed!");
msgBox.exec();
TileWidget *t = (TileWidget *) widget(index) ;
t->deleteLater();
removeTab(index);
}
void TileSheetManager::tabChanged(int index)
{
QMessageBox msgBox;
msgBox.setText("Tab was Changed!");
msgBox.exec();
TileWidget *t;
for(int i = 0; i < count(); i++)
{
t = (TileWidget *) widget(i) ;
t->resetSetBrush();
}
}
Tabs aren't getting closed, selected brushes are not being reset, and I get no messages, so I'm concluding the signals aren't being picked up. Which is weird, because I have used similar code for a previous project, in which case it worked.
Don't use variable names in the connect function :
Note that the signal and slots parameters must not contain
any variable names, only the type.
The connection should be
connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTileWidget(int)));
connect(this, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
Related
I would like to set the font color and the background color if I click on a button.
I just added these two functions to the mainwindow.h file
public:
void createGrid();
private slots:
void clickCell(int row, int col);
mainwindow.cpp
QVector<QVector<QPushButton*>> buttons(10);
void MainWindow::createGrid() {
QFrame *frame = new QFrame(this);
QGridLayout *layout = new QGridLayout(frame);
layout->setMargin(0);
layout->setSpacing(0);
for(int i = 0; i < 10; ++i){
buttons[i].resize(10);
for(int j = 0; j < 10; ++j){
QPushButton *button = new QPushButton("0");
button->setMinimumSize(50,50);
button->setMaximumSize(50,50);
connect(button,SIGNAL(released()),this,SLOT(clickCell(i,j)));
layout->addWidget(button,i,j);
buttons[i][j] = button;
}
}
setCentralWidget(frame);
}
void MainWindow::clickCell(int row, int col) {
buttons[row][col]->setStyleSheet("background-color: grey; color: red");
}
When I run my code I am getting the following outputs about 100 times:
QObject::connect: No such slot MainWindow::clickCell(i,j) in ..\untitled\mainwindow.cpp:41
QObject::connect: (receiver name: 'MainWindow')
As per the comment: use the new signal/slot syntax to invoke a lambda as the slot. So your connect call should be something like (untested)...
connect(button, &QPushButton::released, this,
[=, this]
{
clickCell(i, j);
});
I have an LCDNumber display panel in QT. I want to update the value of it continuously with a variable being received from an external servo motor (the speed)
I have the following code
HANDLE RS232Handle;
UCHAR Address = 0;
UCHAR Status = 0;
int Value = 0;
GetResult(RS232Handle, &Address, &Status, &Value);
printf("Result: Address=%d, Status=%d, Value=%d\n", Address, Status, Value);
ui->lcdNumber_TarRot_Status->display(Value);
All these lines must run to get the proper value. I have looked into calling a function every x seconds, and I have tried a for loop that runs forever, but nothing really works as desired. Is there a proper way of doing this?
Thanks!
I don't know how you tried to "calling a function every x seconds" - most likely you used a blocking wait to do so. Instead, call it from a timer, without blocking the event loop.
class MyClass : public QWidget {
Q_OBJECT
Ui::MyClass ui;
HANDLE m_device = 0;
QBasicTimer m_queryTimer;
void timerEvent(QTimerEvent *event) override {
if (event->timerId() == m_queryTimer.timerId())
queryDevice();
}
void queryDevice() {
UCHAR address = 0;
UCHAR status = 0;
int value = 0;
GetResult(m_device, &address, &status, &value);
qDebug() << "Result: Address" << address << "Status" << status << "Value" << value;
ui->lcdNumber_TarRot_Status->display(value);
}
}
...
public:
explicit MyClass(QObject *parent = nullptr) : QObject(parent) {
ui.setupUi(this);
m_queryTimer.start(1000, this);
...
}
void openDevice() {
...
m_device = ...;
}
};
I ended up using a QTimer since I'm working with QT:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateMCvalues()));
timer->start();
}
void MainWindow::updateMCvalues() {
HANDLE RS232Handle;
UCHAR Address = 0;
UCHAR Status = 0;
int Value = 0;
GetResult(RS232Handle, &Address, &Status, &Value);
printf("Result: Address=%d, Status=%d, Value=%d\n", Address, Status, Value);
ui->lcdNumber_TarRot_Status->display(Value);
}
From the Qt docs on the QLCDNumber class. display() is a slot, not a public function. Calling it directly won't work unless on the UI thread. See here for info on signals and slots if you are unfamiliar.
The proper usage would be to connect a signal of your choosing (i.e. make your own) to the ````display()``` slot.
Say you made a signal called output_number, once connected to the display() slot. You could call:
emit output_number(Value);
Which would in turn call the display slot on the Qt UI thread.
I am trying to count how many buttons have been checked
void pracownik2::on_pushButton_4_clicked()
{
this->setWindowTitle("EKRAN");
QWidget *centralWidget = new QWidget;
int licznik=1;
QString licz;
QString kolumny = ui->lineEdit->text();
QString wiersze = ui->lineEdit_2->text();
QPushButton *button[wiersze.toInt()][kolumny.toInt()];
QGridLayout *controlsLayout = new QGridLayout;
for(int i=0;i<wiersze.toInt();i++)
{
for(int j=0;j<kolumny.toInt();j++)
{
licz = QString::number(licznik);
licznik++;
button[i][j] = new QPushButton(licz);
button[i][j]->setCheckable(1);
controlsLayout->addWidget(button[i][j], i, j);
}
}
QPushButton *okej = new QPushButton("Zatwierdź");
QPushButton *anul = new QPushButton("Anuluj");
controlsLayout->addWidget(okej, wiersze.toInt(), 0);
controlsLayout->addWidget(anul, wiersze.toInt(), 1);
controlsLayout->setHorizontalSpacing(0);
controlsLayout->setVerticalSpacing(0);
centralWidget->setLayout(controlsLayout);
setCentralWidget(centralWidget);
for(int i=0;i<wiersze.toInt();i++)
{
for(int j=0;j<kolumny.toInt();j++)
{
connect(button[i][j],SIGNAL(toggled(bool)),this,SLOT(tescik()));
}
}
connect(anul,SIGNAL(clicked()),this,SLOT(close()));
connect(okej,SIGNAL(clicked()),this,SLOT(okay2()));
}
void pracownik2::tescik()
{
miejsca++;
}
void pracownik2::okay2()
{
QString m=QString::number(miejsca);
QMessageBox::information(this,"elo","wybranych miejsc: " + m);
}
If i check buttons number 1,2,3 and press okay button it shows that 3 buttons have been checked BUT if I check button number 1 and uncheck it and press okay it shows that 2 buttons have been checked. How to make my variable increment only if I check button, not also when I uncheck it?
I'm sorry for the code edit, just couldn't make it look better
The signal toggled has a boolean parameter, add it to your slot, and adjust count according to it. Change connect:
connect(button[i][j],SIGNAL(toggled(bool)),this,SLOT(tescik(bool)));
And change slot:
void pracownik2::tescik(bool t) {
if (t) miejsca++;
else miejsca--;
}
I have a segment of code that calls a mousePressEvent. I have the left-click output the coordinates of the cursor, and I have rightclick do the same, but I also want to have the rightclick open a context menu. The code I have so far is:
void plotspace::mousePressEvent(QMouseEvent*event)
{
double trange = _timeonright - _timeonleft;
int twidth = width();
double tinterval = trange/twidth;
int xclicked = event->x();
_xvaluecoordinate = _timeonleft+tinterval*xclicked;
double fmax = Data.plane(X,0).max();
double fmin = Data.plane(X,0).min();
double fmargin = (fmax-fmin)/40;
int fheight = height();
double finterval = ((fmax-fmin)+4*fmargin)/fheight;
int yclicked = event->y();
_yvaluecoordinate = (fmax+fmargin)-finterval*yclicked;
cout<<"Time(s): "<<_xvaluecoordinate<<endl;
cout<<"Flux: "<<_yvaluecoordinate<<endl;
cout << "timeonleft= " << _timeonleft << "\n";
returncoordinates();
emit updateCoordinates();
if (event->button()==Qt::RightButton)
{
contextmenu->setContextMenuPolicy(Qt::CustomContextMenu);
connect(contextmenu, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(ShowContextMenu(const QPoint&)));
void A::ShowContextMenu(const QPoint &pos)
{
QMenu *menu = new QMenu;
menu->addAction(tr("Remove Data Point"), this,
SLOT(test_slot()));
menu->exec(w->mapToGlobal(pos));
}
}
}
I know that my problem is very fundamental in nature, and that 'contextmenu' is not properly declared. I have pieced together this code from many sources, and do not know how to declare something in c++. Any advice would be greatly appreciated.
customContextMenuRequested is emitted when the widget's contextMenuPolicy is Qt::CustomContextMenu, and the user has requested a context menu on the widget. So in the constructor of your widget you can call setContextMenuPolicy and connect customContextMenuRequested to a slot to make a custom context menu.
In the constructor of plotspace :
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(ShowContextMenu(const QPoint &)));
ShowContextMenu slot should be a class member of plotspace like :
void plotspace::ShowContextMenu(const QPoint &pos)
{
QMenu contextMenu(tr("Context menu"), this);
QAction action1("Remove Data Point", this);
connect(&action1, SIGNAL(triggered()), this, SLOT(removeDataPoint()));
contextMenu.addAction(&action1);
contextMenu.exec(mapToGlobal(pos));
}
I'm working on a project where i'm trying to add a QPushButton into a QTableView.
also i want to connect that button to open a document from a database. So far i added the button and i wrote the connect statement for it but when i click on the button nothing happened.
here is my code
void MainWindow::DocumentTable()
{
tableview = new QTableView;
query = new QSqlQueryModel(this);
signalMapper = new QSignalMapper(this);
foreach(it,treeWidget->selectedItems())
{
for (int col=0; col< it->columnCount(); ++col)
{
qDebug() << col << it->text(col);
QSqlQuery qry;
qry.prepare("select * from document where Folno=:Folno");
qry.bindValue(":Folno", it->text(col));
qry.exec();
query->setQuery(qry);
tableview->setModel(query);
tableview->setEditTriggers(QAbstractItemView::NoEditTriggers);
for (int i = 0; i< 1000; i++)
{
button= new QPushButton("Open Document");
tableview->setIndexWidget(tableview->model()->index(i, 0), button);
signalMapper->setMapping(button, i);
}
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(imageFROMdatabase()));
tableview->show();
Docwidget= new QDockWidget(this);
Docwidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
Docwidget->setWidget(tableview);
addDockWidget(Qt::RightDockWidgetArea,Docwidget);
Docwidget->show();
if(!query->submit())
{
QMessageBox::warning(0,"Error",query->lastError().text());
}
db.close();
}
}
}
and this is the slot function
void MainWindow::imageFROMdatabase()
{
QSqlQuery imageQuery;
imageQuery.prepare("SELECT * from doc_page where doc_no=:doc_no and f_number=:f_number");
imageQuery.bindValue(":doc_no", 1);
imageQuery.bindValue(":f_number",1);
imageQuery.exec();
imageQuery.next();
if( imageQuery.lastError().isValid())
{
QMessageBox::warning(0,"Error",imageQuery.lastError().text());
// QSqlDatabase::database().rollback();
}
else
{
// QByteArray ba1 = imageQuery.value(1).toByteArray();
QPixmap pic;
pic.loadFromData( ba);
scrollArea = new QScrollArea;
scrollArea->setBackgroundRole(QPalette::Dark);
scrollArea->setEnabled(true);
QString fileName = QFileDialog::getOpenFileName(this,"Open Image File",QDir::currentPath());
QImage image(fileName);
scene = new QGraphicsScene();
view = new QGraphicsView(scene);
item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
scene->addItem(item);
xwidget= new QDockWidget(this);
xwidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
xwidget->setWidget(view);
addDockWidget(Qt::RightDockWidgetArea,xwidget);
xwidget->show();
db.close();
}
}
please tell if anything wrong in these codes.
The slot method is not same as signal method. They should have exact equal signatures. qDebug() should have generated some warnings for you. Read outputs carefully. imageFROMDatabase() method should accept an integer as its input too. Signals are not real functions. They are used to trigger another function which is matched in signature with them.
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(imageFROMdatabase()));
Change it like this :
connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(imageFROMdatabase(int)));
ans also :
void MainWindow::imageFROMdatabase( int x ) { ... }
Also if the signals and slots are not in a thread read the manual enum Qt::ConnectionType