QWidget::insertAction Attempt to insert null action at runtime - c++

So, I'm trying to run my spreadsheet application in QT Creator and it compiles without errors, but when I try to run the application I get the following error QWidget::insertAction Attempt to insert null action. The problem is that I have no idea where the issue is coming from... The error is not appearing in the error section of QT Creator but in the little terminal created when running programs.
I have a createActions() function that initializes all the actions initilized in the header, maybe is coming from there?
The actions in the private part of the header look like this:
QAction *newAction;
QAction *openAction;
QAction *aboutQtAction;
QAction *closeAction;
QAction *exitAction;
QAction *selectAllAction;
QAction *showGridAction;
QAction *saveAction;
QAction *saveAsAction;
QAction *cutAction;
QAction *copyAction;
QAction *pasteAction;
QAction *deleteAction;
QAction *selectRowAction;
QAction *selectColumnAction;
QAction *findAction;
QAction *goToCellAction;
QAction *recalculateAction;
QAction *sortAction;
QAction *autoRecalcAction;
QAction *aboutAction;
Here's the function:
void MainWindow::createActions()
{
newAction = new QAction(tr("&New"), this);
newAction->setIcon(QIcon(":/images/avatar.jpeg"));
newAction->setShortcut(QKeySequence::New);
newAction->setStatusTip(tr("Create a new spreadsheet file"));
connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));
for (int i = 0; i < MaxRecentFiles; ++i) {
recentFileActions[i] = new QAction(this);
recentFileActions[i]->setVisible(false);
connect(recentFileActions[i], SIGNAL(triggered()),this, SLOT(openRecentFile()));
}
closeAction = new QAction(tr("&Close"), this);
closeAction->setShortcut(QKeySequence::Close);
closeAction->setStatusTip(tr("Close this window"));
connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
exitAction = new QAction(tr("E&xit"), this);
exitAction->setShortcut(tr("Ctrl+Q"));
exitAction->setStatusTip(tr("Exit the application"));
connect(exitAction, SIGNAL(triggered()),
qApp, SLOT(closeAllWindows()));
selectAllAction = new QAction(tr("&All"), this);
selectAllAction->setShortcut(QKeySequence::SelectAll);
selectAllAction->setStatusTip(tr("Select all the cells in the "
"spreadsheet"));
connect(selectAllAction, SIGNAL(triggered()),
spreadsheet, SLOT(selectAll()));
showGridAction = new QAction(tr("&Show Grid"), this);
showGridAction->setCheckable(true);
showGridAction->setChecked(spreadsheet->showGrid());
showGridAction->setStatusTip(tr("Show or hide the spreadsheet's "
"grid"));
connect(showGridAction, SIGNAL(toggled(bool)),
spreadsheet, SLOT(setShowGrid(bool)));
aboutQtAction = new QAction(tr("About &Qt"), this);
aboutQtAction->setStatusTip(tr("Show the Qt library's About box"));
connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}
These actions, after being created, are added to the menus in the createMenus() function:
void MainWindow::createMenus(){
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(newAction);
fileMenu->addAction(openAction);
fileMenu->addAction(saveAction);
fileMenu->addAction(saveAsAction);
separatorAction = fileMenu->addSeparator();
for (int i = 0; i < MaxRecentFiles; ++i)
fileMenu->addAction(recentFileActions[i]);
fileMenu->addSeparator();
fileMenu->addAction(exitAction);
...
Someone has any idea where this error is coming from?
Thanks!
Axel

In createActions(), you don't appear to be initializing openAction, saveAction, or saveAsAction - which you then insert into your menu. I'd guess that's the problem, unless you just didn't include the code initializing those particular actions.

Related

removing white separator form between QMenu and QToolBar

I have written QMenu and QToolBar in Qt.
That's what I got:
I can't find any way to remove this white separator between QMenu(File, Edit) and QToolBar(Two buttons with piano icons).
Code:
MainWindow::MainWindow()
{
this->setStyleSheet("background-color: black;");
initMenu();
initButtons();
}
void MainWindow::initMenu()
{
menuBar()->setStyleSheet("background: #555555; "
"color: #EEEEEE; "
"selection-background-color: #222222; "
"border-color:#EEEEEE;");
QMenu *fileMenu = menuBar()->addMenu("File");
QAction *newFileAction = new QAction("New", this);
newFileAction->setShortcut(QKeySequence::New);
newFileAction->setStatusTip("Create new file.");
//connect
fileMenu->addAction(newFileAction);
QAction *openFileAction = new QAction("Open", this);
openFileAction->setShortcut(QKeySequence::Open);
openFileAction->setStatusTip("Open file.");
//connect
fileMenu->addAction(openFileAction);
QAction *saveFileAction = new QAction("Save", this);
saveFileAction->setShortcut(QKeySequence::Save);
saveFileAction->setStatusTip("Save file.");
//connect
fileMenu->addAction(saveFileAction);
QAction *saveAsFileAction = new QAction("Save as", this);
saveAsFileAction->setShortcut(QKeySequence::SaveAs);
saveAsFileAction->setStatusTip("Save file as another file.");
//connect
fileMenu->addAction(saveAsFileAction);
fileMenu->addSeparator();
QAction *quitAction = new QAction("Quit", this);
quitAction->setShortcut(QKeySequence::Quit);
quitAction->setStatusTip("Quit program.");
//connect
fileMenu->addAction(quitAction);
QMenu *editMenu = menuBar()->addMenu("Edit");
QAction *copyAction = new QAction("Copy", this);
copyAction->setShortcut(QKeySequence::Copy);
copyAction->setStatusTip("Copy.");
//connect
editMenu->addAction(copyAction);
}
void MainWindow::initButtons()
{
QToolBar *buttonToolBar = addToolBar("Buttons");
buttonToolBar->setStyleSheet("background: #555555");
buttonToolBar->setMovable(false);
const QIcon pianoIcon = QIcon::fromTheme("piano-roll",QIcon(":/buttons/b_piano.png"));
QAction *pianoAction = new QAction(pianoIcon, tr("&Piano Roll"), this);
pianoAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_1));
pianoAction->setStatusTip("Opens Piano Roll window.");
//connect();
buttonToolBar->addAction(pianoAction);
const QIcon piano2Icon = QIcon::fromTheme("piano-roll2",QIcon(":/buttons/i_piano.png"));
QAction *piano2Action = new QAction(piano2Icon, tr("&Piano Roll"), this);
piano2Action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_2));
piano2Action->setStatusTip("Opens Piano Roll window number two.");
//connect();
buttonToolBar->addAction(piano2Action);
}
In MainWindow I run two functions. First function creates Qmenu. Second one creates QToolBar with two buttons.

Qt - connect menuBar and QWidget

So I have menu bar like this:
this->layout = new QGridLayout;
QMenuBar* menuBar = new QMenuBar();
QMenu *fileMenu = new QMenu("File");
menuBar->addMenu(fileMenu);
fileMenu->addAction("Exit");
this->layout->setMenuBar(menuBar);
And I am wonderig how to connect thie action "Exit" with some slot my QWidget, I tryed something like this:
connect(menuBar,SIGNAL(menuBar->actions),this,SLOT(exitGame()));
But it is not working, can you tell me what I am doing wrong? And yes I have read manual about QMenuBar bud there are no examples of connecting. I have read about some connecting in Qt Designer but I am not using it.
You need to connect the QAction pointer returned from QMenuBar::addAction to the slot...
auto *exit_action = fileMenu->addAction("Exit");
connect(exit_action, &QAction::triggered,
[this](bool checked)
{
exitGame();
});

How to add a slot to a QWidget?

I have a QMainWindow, which has a QAction whose signal triggered() is connected to a slot about2().
...
connect(mAboutAction2, SIGNAL(triggered()), this, SLOT(about2()));
...
void occQt::about2() //UI
{
QWidget* pWidget = new QWidget;
QPushButton* okbtn = new QPushButton(tr("ok"));
QPushButton* cancelbtn = new QPushButton(tr("cancel"));
btnlayout->addWidget(okbtn);
btnlayout->addWidget(cancelbtn);
dlglayout->setMargin(50);
dlglayout->addLayout(gridlayout);
dlglayout->addStretch(40);
dlglayout->addLayout(btnlayout);
pWidget->setLayout(dlglayout);
pWidget->setWindowTitle(tr("Make a Box by custom."));
pWidget->show();
connect(okbtn, SIGNAL(clicked()), pWidget, SLOT(make_a_box()));
connect(cancelbtn, SIGNAL(clicked()), pWidget, SLOT(close()));
}
void occQt::make_a_box()
{
TopoDS_Shape aTopoBox = BRepPrimAPI_MakeBox(3.0, 4.0, 95.0).Shape();
Handle_AIS_Shape anAisBox = new AIS_Shape(aTopoBox);
anAisBox->SetColor(Quantity_NOC_AZURE);
mContext->Display(anAisBox);
}
When I run the slot about2(), the UI opens. I can close it when I click the cancelbtn, but I can't enter the slot make_a_box().
Where can I add this slot in order to make this code working?
This is ok and runs fine, because the slot you are using is located at the right place : in your occQt class.
// You connect the signal FROM the action TO "this", i.e. your class
connect(mAboutAction2, SIGNAL(triggered()), this, SLOT(about2()));
void occQt::about2() //UI
{
QWidget* pWidget = new QWidget;
QPushButton* okbtn = new QPushButton(tr("ok"));
QPushButton* cancelbtn = new QPushButton(tr("cancel"));
btnlayout->addWidget(okbtn);
btnlayout->addWidget(cancelbtn);
dlglayout->setMargin(50);
dlglayout->addLayout(gridlayout);
dlglayout->addStretch(40);
dlglayout->addLayout(btnlayout);
pWidget->setLayout(dlglayout);
pWidget->setWindowTitle(tr("Make a Box by custom."));
pWidget->show();
Now, this is not ok :
// You connect the signal FROM the button to pWidget, which doesn't have a slot make_a_box()
connect(okbtn, SIGNAL(clicked()), pWidget, SLOT(make_a_box()));
The slot make_a_box() doesn't exist for pWidget, which is a QWidget. You are trying to connect a signal to a slot that does not exist.
You have to define this slot in your occQt class, and connect the signal clicked() of the button to your slot in your class :
// Now, you connect the signal FROM the button to "this", which is your class and has a slot make_a_box()
connect(okbtn, SIGNAL(clicked()), this, SLOT(make_a_box()));
In your .h file, you will have :
private slots :
void make_a_box();
And in your .cpp file :
void occQt::make_a_box()
{
TopoDS_Shape aTopoBox = BRepPrimAPI_MakeBox(3.0, 4.0, 95.0).Shape();
Handle_AIS_Shape anAisBox = new AIS_Shape(aTopoBox);
anAisBox->SetColor(Quantity_NOC_AZURE);
mContext->Display(anAisBox);
}

What is the most popular/standard way to customize order of context menus in QT?

I'm pasting code snippet from : http://qt-project.org/doc/qt-5.0/qtwidgets/mainwindows-menus.html
void MainWindow::createActions()
{
newAct = new QAction(tr("&New"), this);
newAct->setShortcuts(QKeySequence::New);
newAct->setStatusTip(tr("Create a new file"));
connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
openAct = new QAction(tr("&Open..."), this);
openAct->setShortcuts(QKeySequence::Open);
openAct->setStatusTip(tr("Open an existing file"));
connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
saveAct = new QAction(tr("&Save"), this);
saveAct->setShortcuts(QKeySequence::Save);
saveAct->setStatusTip(tr("Save the document to disk"));
connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
}
Now I want to give user an option to customize the order of "menu addition", i.e. I want this sequence New, Open and Save to be dynamically decided at run time.
How can I achieve this in QT?
What is the standard way to make menus customize-able?

how to use mousePressEvent on QPushButtons

I've made some QPushbuttons like QPushButton **btn and I want to know when the user clicks on one of them using QMouseEvent here is the code but this idea does not work at all any ideas??
void Game::mousePressEvent(QMouseEvent *ev)
{
if(ev->button() == Qt::LeftButton)
{
btn[ev->x()][ev->y()].setStyleSheet("background-color : black;");
}
else
{
btn[ev->x()][ev->y()].setStyleSheet("background-color : red;");
}
that else part is for right click
and here is the code that generates the buttons
void Game::MakeButton()
{
btn = new ApButton*[column];
hrztl = new QHBoxLayout[column];
hrztl->setSpacing(0);
for(int i=0; i<column;i++)
{
btn[i] = new ApButton[row];
for(int j=0; j<row; j++)
{
btn[i][j].setRowCol(i,j);
btn[i][j].setFixedSize(50,50);
hrztl[i].addWidget(&btn[i][j]);
}
ui->MainLayout->addLayout(&hrztl[i]);
}
ui->MainLayout->setSpacing(0);
}
ApButton is a class that inherits QPushButton
This is a good example of use for a QSignalMapper, as seen there: http://qt-project.org/doc/qt-5.0/qtcore/qsignalmapper.html#details
ButtonWidget::ButtonWidget(QStringList texts, QWidget *parent)
: QWidget(parent)
{
signalMapper = new QSignalMapper(this);
QGridLayout *gridLayout = new QGridLayout;
for (int i = 0; i < texts.size(); ++i) {
QPushButton *button = new QPushButton(texts[i]);
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(button, texts[i]);
gridLayout->addWidget(button, i / 3, i % 3);
}
connect(signalMapper, SIGNAL(mapped(QString)),
this, SIGNAL(clicked(QString)));
setLayout(gridLayout);
}
In that example, every button is identified by its title, as a QString. The mapper allows you to retrieve the corresponding button's title when one of them is clicked.
Switch your
Game::mousePressEvent(QMouseEvent *e)
to
ApButton::mousePressEvent(QMouseEvent *e)
since you are trying to implement the Press Event of the Button. If you only want to have the moment of the button being pressed and not changing Button behaviour with this, use a SIGNAL/SLOT connection instead of reimplementing the event (add to your creation):
connect(btn[i][j], SIGNAL(pressed()), this, SLOT(slotButtonPressed());
void Game::slotButtonPressed(){
//doSomething
}
use a QButtonGroup or the QSignalMapper if you need to identify more then one Button in a single method or use QObject::sender(), but this can be tricky sometimes.
I had a similar situations some times ago.. I had a QDialog and I had to dinamically add some QPushButton.. then I need to know on which button the user pressed.. so I needed something like:
connect( btn, SIGNAL( clicked(int) ),
this, SLOT( handle(int) ));
for instance a signal-slot connection with the id of the clicked button and a function for handle the click. The function is the same for each buttons and can handle the specific button because of the id..
Implementing this is quite simple subclassing QPushButton adding an id and a new signal..
Hope it's some help!
If Apbutton inherits QPushButton, why don't connect to clicked()?
then you can call QObject::sender()
On slot:
ApButton *but = dynamic_cast<ApButton*>QObject::sender()
if(but)
{
but->setStyleSheet("background-color : black;");
}
to get the clicked buttonbutton and set its stylesheet