removing white separator form between QMenu and QToolBar - c++

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.

Related

When qlabel is resized Layout is not updated

I am trying to implement a camera view app in Qt, but I don't know why It doesn't fix correctly layout / buttons. First, before to update the qlabel, I have this:
But when I click the start button. the GUI changes to this:
The code to create the window is:
cameraLabel = new QLabel(tr("No camera loaded"));
cameraLabel->setAlignment(Qt::AlignCenter);
cameraLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
cameraLabel->setBackgroundRole(QPalette::Dark);
cameraLabel->setAutoFillBackground(true);
createButtons();
...
..
.
mainLayout = new QHBoxLayout;
mainLayout->addWidget(cameraLabel);
mainLayout->addLayout(buttonsLayout);
setLayout(mainLayout);
void CameraPlayer::createButtons()
{
QSize iconSize(36, 36);
playButton = new QToolButton;
playButton->setIcon(style()->standardIcon(QStyle::SP_MediaPlay));
playButton->setIconSize(iconSize);
playButton->setToolTip(tr("Play"));
connect(playButton, SIGNAL(clicked()), this, SLOT(play()));
snapshotButton = new QToolButton;
snapshotButton->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton));
snapshotButton->setIconSize(iconSize);
snapshotButton->setToolTip(tr("Snapshot"));
connect(snapshotButton, SIGNAL(clicked()), this, SLOT(snapshot()));
stopButton = new QToolButton; cameraLabel = new QLabel(tr("No camera loaded"));
cameraLabel->setAlignment(Qt::AlignCenter);
cameraLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
cameraLabel->setBackgroundRole(QPalette::Dark);
cameraLabel->setAutoFillBackground(true);
createButtons();
SParameters& globalParams = GlobalParameters::Instance().params;
globalParams.IPAddress = "169.251.0.1";
globalParams.isColor = true;
globalParams.timer_s =10;
timerIdCamera = 0;
mainLayout = new QHBoxLayout;
mainLayout->addWidget(cameraLabel);
mainLayout->addLayout(buttonsLayout);
setLayout(mainLayout);
stopButton->setIcon(style()->standardIcon(QStyle::SP_MediaStop));
stopButton->setIconSize(iconSize);
stopButton->setToolTip(tr("Stop"));
connect(stopButton, SIGNAL(clicked()), this, SLOT(stop()));
colorButton = new QPushButton;
colorButton->setText(tr("WB / Color"));
connect(colorButton, SIGNAL(clicked()), this, SLOT(changeColor()));
buttonsLayout = new QVBoxLayout;
buttonsLayout->addStretch();
buttonsLayout->addWidget(playButton);
buttonsLayout->addWidget(snapshotButton);
buttonsLayout->addWidget(stopButton);
buttonsLayout->addWidget(colorButton);
buttonsLayout->addStretch();
}
To udpate the qLabel,It is configured a timer / trigger which is called every x milsecs and update the qlabel object:
void CameraPlayer::timerEvent(QTimerEvent *event){
try
{
if (timerIdCamera!=0)
{
if (camera.CameraHasImage())
{
QImage *qImage = camera.CameraGrab();
if (qImage!=NULL && SIZE_IMAGE!=QString::number(qImage->byteCount()))
{
cameraLabel->setPixmap(QPixmap::fromImage(*qImage));
cameraLabel->setFixedWidth(qImage->width());
cameraLabel->show();
}
delete[] qImage->bits();
delete qImage;
}
}
}
catch (std::exception &ex)
{
QMessageBox qMBox;
qMBox.setText(QString::fromUtf8(ex.what()));
qMBox.exec();
}
}
The problem is here
cameraLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
I was ignoring layout policies from other widgets / layouts. I commented this and It started to work well.

How to show the row where QPushButton is clicked in QTableWidget

I would like to delete row where QPushButton is clicked how it is possible to I think it is reasonable to use slots but how to do it don't know , if you have any ideas how to get a row of selected button please share, thanks.
It is my table
It is a code where i add rows to my QTableWidget
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
for(int i = 0; i<20;i++)
ui->tableWidget->insertRow(ui->tableWidget->rowCount());
QVector<QString>vec;
vec<<"first"<<"sec"<<"third"<<"for"<<"fif"<<"first"<<"sec"
<<"third"<<"for"<<"fif";
vec<<"first"<<"sec"<<"third"<<"for"<<"fif"<<"first"<<"sec"
<<"third"<<"for"<<"fif";
for(int i = 0; i<ui->tableWidget->rowCount();i++)
{
for(int j = 0; j<ui->tableWidget->columnCount();j++)
{
if(j == 0)
{
QWidget* pWidget = new QWidget();
QPushButton* btn_edit = new QPushButton();
btn_edit->setText("Remove");
QHBoxLayout* pLayout = new QHBoxLayout(pWidget);
pLayout->addWidget(btn_edit);
pLayout->setAlignment(Qt::AlignCenter);
pLayout->setContentsMargins(0, 0, 0, 0);
pWidget->setLayout(pLayout);
ui->tableWidget->setCellWidget(i, j, pWidget);
continue;
}
QTableWidgetItem*item = new QTableWidgetItem(vec[i]);
item->setFlags(item->flags() ^ Qt::ItemIsEditable);
ui->tableWidget->setItem(i, j, item);
}
}
}
This task can be solved using the removeRow() method but before we must get the row. First of all we will connect all the buttons to a slot inside the loop as shown below:
*.h
private slots:
void onClicked();
*.cpp
[...]
QPushButton* btn_edit = new QPushButton();
btn_edit->setText("Remove");
connect(btn_edit, &QPushButton::clicked, this, &MainWindow::onClicked);
[...]
In the slot we can get the button that emits the signal through the sender() method, then we get QWidget parent (created with the name pWidget), this is the widget that is added to the QTableWidget and its position is relative to it, then we use the method indexAt() to get the QModelIndex associated with the cell, and this has the information of the row through the method row(). All of the above is implemented in the following lines:
void MainWindow::onClicked()
{
QWidget *w = qobject_cast<QWidget *>(sender()->parent());
if(w){
int row = ui->tableWidget->indexAt(w->pos()).row();
ui->tableWidget->removeRow(row);
ui->tableWidget->setCurrentCell(0, 0);
}
}
Note: The setCurrentCell() method is used to set the focus since the last cell that has it has been deleted.
The complete example can be found in the following link.
When you are creating QPushButton just add :
btn_delete = new QPushButton("Remove", ui->tableWidget);
btn_delete->setObjectName(QString("%1").arg(ui->tableWidget->rowCount()));
connect(btn_delete, SIGNAL(clicked()), this, SLOT(CellButtonDeleteClicked()));
And create function CellButtonDeleteClicked()
void CellButtonDeleteClicked()
{
// by this line I can get the sender of signal
QPushButton *pb = qobject_cast<QPushButton *>(QObject::sender());
int row = pb->objectName().toInt();
ui->tableWidget->removeRow(row);
}

Qt C++, action on clicking QPushButton made dynamically

In one of my windows I made a button responsible for creating dynamic array of buttons. After they are made I can't make 'anul' button close the window
Here's the code
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");
if(anul->isDown() == true)
this->close();
controlsLayout->addWidget(okej, wiersze.toInt(), 0);
controlsLayout->addWidget(anul, wiersze.toInt(), 1);
controlsLayout->setHorizontalSpacing(0);
controlsLayout->setVerticalSpacing(0);
centralWidget->setLayout(controlsLayout);
setCentralWidget(centralWidget);
I also tried to change this->close() with centralWidget->close()
This code is executed one time only.
if(anul->isDown() == true)
this->close();
What you want is to connect the clicked() signal of the button to a function (slot)
connect(anul, SIGNAL(clicked()), this,SLOT(close()))

QWidget::insertAction Attempt to insert null action at runtime

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.

QWidget - resize animation

Say I have a QHBoxLayout where there are 2 QTextEdits and between them a button with an arrow to the right. When you click on the button, the right-side QTextEdit gradually closes by moving the left border until it meets the right one. Simultaneously, the right border of the left QTextEdit takes the place which the right QTextEdit released. And after pressing on the button, the state of the system is coming to the former one.
EDIT: In order to organize this I have done the following:
1) In header file:
class MyWidget : public QWidget
{
Q_OBJECT
QTextEdit *m_textEditor1;
QTextEdit *m_textEditor2;
QPushButton *m_pushButton;
QHBoxLayout *m_layout;
int m_deltaX;
public:
MyWidget(QWidget * parent = 0);
~MyWidget(){}
private slots:
void closeOrOpenTextEdit2(bool isClosing);
};
2) In the source file:
MyWidget::MyWidget(QWidget * parent):QWidget(parent),m_deltaX(0)
{
m_pushButton = new QPushButton(this);
m_pushButton->setText(">");
m_pushButton->setCheckable(true);
connect(m_pushButton, SIGNAL(clicked(bool)), this, SLOT(closeOrOpenTextEdit2(bool)));
m_textEditor1 = new QTextEdit(this);
m_textEditor1->setText("AAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAA AAAAAAAAAAA AAAAAAAAAAA AA");
m_textEditor2 = new QTextEdit(this);
m_layout = new QHBoxLayout;
m_layout->addWidget(m_textEditor1);
m_layout->addWidget(m_pushButton);
m_layout->addWidget(m_textEditor2);
setLayout(m_layout);
}
void MyWidget::closeOrOpenTextEdit2(bool isClosing)
{
QPropertyAnimation *animation1 = new QPropertyAnimation(m_textEditor2, "geometry");
QPropertyAnimation *animation2 = new QPropertyAnimation(m_pushButton, "geometry");
QPropertyAnimation *animation3 = new QPropertyAnimation(m_textEditor1, "geometry");
if(isClosing) //close the second textEdit
{
m_pushButton->setText("<");
QRect te2_1 = m_textEditor2->geometry();
m_deltaX = te2_1.width()-3;
QRect te2_2(te2_1.x()+m_deltaX, te2_1.y(), 3 ,te2_1.height());
QRect pb_1 = m_pushButton->geometry();
QRect pb_2(pb_1.x()+m_deltaX, pb_1.y(), pb_1.width() ,pb_1.height());
QRect te1_1 = m_textEditor1->geometry();
QRect te1_2(te1_1.x(), te1_1.y(), te1_1.width()+m_deltaX, te1_1.height());
//animation->setDuration(10000);
animation1->setStartValue(te2_1);
animation1->setEndValue(te2_2);
animation2->setStartValue(pb_1);
animation2->setEndValue(pb_2);
animation3->setStartValue(te1_1);
animation3->setEndValue(te1_2);
}
else //open
{
m_pushButton->setText(">");
QRect te2_1 = m_textEditor2->geometry();
QRect te2_2(te2_1.x()-m_deltaX, te2_1.y(), 3+m_deltaX ,te2_1.height());
QRect pb_1 = m_pushButton->geometry();
QRect pb_2(pb_1.x()-m_deltaX, pb_1.y(), pb_1.width() ,pb_1.height());
QRect te1_1 = m_textEditor1->geometry();
QRect te1_2(te1_1.x(), te1_1.y(), te1_1.width()-m_deltaX, te1_1.height());
//animation->setDuration(10000);
animation1->setStartValue(te2_1);
animation1->setEndValue(te2_2);
animation2->setStartValue(pb_1);
animation2->setEndValue(pb_2);
animation3->setStartValue(te1_1);
animation3->setEndValue(te1_2);
}
animation1->start();
animation2->start();
animation3->start();
}
EDIT:
And I have the following problem:
When I close the second QTextEdit (by clicking on the button) and resize the MyWidget, then the QTextEdit restores its state (but it should stay closed of course). How can I solve this problem?
Please provide me with a code snippet.
Qt's Animation framework sounds like a good place to start. You could just try to follow their tutorials, adapting for you use case. I have used it already, and it seemed quite straight forward.
1) You could replace your button with a vertical layout, place the button inside this layout and finally add a vertical spacer below the button (in same the layout).
...
QVBoxLayout* m_buttonLayout = new QVBoxLayout();
m_layout = new QHBoxLayout();
m_layout->addWidget(m_textEditor1);
m_layout->addLayout(m_buttonLayout);
m_layout->addWidget(m_textEditor2);
m_buttonLayout->addWidget(m_pushButton);
m_buttonLayout->addItem( new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding) );
2) I guess you could (and should) animate widget's maximumSize (or just maximumWidth) property and let the layout take care of calculating actual geometries. This would also simplify your calculations. E.g.
QPropertyAnimation *animation1 = new QPropertyAnimation(m_textEditor2, "maximumWidth");
QPropertyAnimation *animation2 = new QPropertyAnimation(m_textEditor, "maximumWidth");
if (isClosing)
{
int textEdit2_start = m_textEditor2->maximumWidth();
int textEdit2_end = 0;
int textEdit_start = m_textEditor->maximumWidth();
int textEdit_end = textEdit_start + textEdit2_start;
animation1->setStartValue(textEdit2_start);
...
}
Also, now you don't have to animate buttons geometry at all (assuming that you have set fixed size to it).
PS. I didn't compile codes so there might be minor errors but you should get the idea.
Here what I wanted:
Header file
class MyWidget : public QWidget
{
Q_OBJECT
QTextEdit *m_textEditor1;
QTextEdit *m_textEditor2;
QPushButton *m_pushButton;
QHBoxLayout *m_layout;
QVBoxLayout *m_buttonLayout;
int m_deltaX;
bool m_isClosed;
public:
MyWidget(QWidget * parent = 0);
~MyWidget(){}
void resizeEvent( QResizeEvent * event );
private slots:
void closeOrOpenTextEdit2(bool isClosing);
};
Source file
MyWidget::MyWidget(QWidget * parent):QWidget(parent),m_deltaX(0)
{
m_pushButton = new QPushButton(this);
m_pushButton->setText(">");
m_pushButton->setCheckable(true);
m_pushButton->setFixedSize(16,16);
connect(m_pushButton, SIGNAL(clicked(bool)), this, SLOT(closeOrOpenTextEdit2(bool)));
m_textEditor1 = new QTextEdit(this);
m_textEditor1->setText("AAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAA AAAAAAAAAAA AAAAAAAAAAA AA");
m_textEditor2 = new QTextEdit(this);
m_buttonLayout = new QVBoxLayout();
m_buttonLayout->addWidget(m_pushButton);
m_buttonLayout->addItem( new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding) );
m_layout = new QHBoxLayout;
m_layout->addWidget(m_textEditor1, 10);
m_layout->addSpacing(15);
m_layout->addLayout(m_buttonLayout);
m_layout->setSpacing(0);
m_layout->addWidget(m_textEditor2, 4);
setLayout(m_layout);
resize(800,500);
}
void MyWidget::closeOrOpenTextEdit2(bool isClosing)
{
m_isClosed = isClosing;
QPropertyAnimation *animation1 = new QPropertyAnimation(m_textEditor2, "maximumWidth");
if(isClosing) //close the second textEdit
{
m_textEditor2->setMaximumWidth(m_textEditor2->width());
int textEdit2_start = m_textEditor2->maximumWidth();
m_deltaX = textEdit2_start;
int textEdit2_end = 3;
animation1->setDuration(500);
animation1->setStartValue(textEdit2_start);
animation1->setEndValue(textEdit2_end);
m_pushButton->setText("<");
}
else //open
{
int textEdit2_start = m_textEditor2->maximumWidth();
int textEdit2_end = m_deltaX;
animation1->setDuration(500);
animation1->setStartValue(textEdit2_start);
animation1->setEndValue(textEdit2_end);
m_pushButton->setText(">");
}
animation1->start();
}
void MyWidget::resizeEvent( QResizeEvent * event )
{
if(!m_isClosed)
m_textEditor2->setMaximumWidth( QWIDGETSIZE_MAX );
}