cant exchange widget in QSplitter (Qt) - c++

I have a QSplitter with two widgets. One of them is static, the other one is supposed to change on the press of a button. But the problem is the widget does not change?
I have a pointer for the widget that is changing - this->content
The widget to switch to is in the pointer named widget.
Here's a code snippet where I switch the widget:
qDebug() << "before: " << this->content;
this->content = widget;
qDebug() << "after: " << this->content;
this->content->update();
this->content->repaint();
My debug output there verifies that the pointer points to the other widget:
before: QLineEdit(0x363850)
after: SCTableView(0x3644c0)
Trying to make it show by calling update() and repaint(), without any success.
Any ideas?

Problem solved. Got help from some people in #qt on freenode. Thanks.
I forgot to call setVisible(true) on this->content after switching to the new widget.

Related

Qt value from lineEdit and isChecked from QCheckBox not working as expected

I'm trying to make a QMessageBox pop up when I press a submit button, which works fine, however the message inside is dependent based on whether some checkboxes are checked, and on the value of the line-edit, as such:
QApplication a(argc, argv);
QMainWindow *w = new QMainWindow();
.
.
.
QPushButton but_submit("Submit");
QMessageBox msg_submit;
// The following will be so that we can get the val of the GPA and then add it
// To the full message that will contain the info of person
QString submit_string = "Hello, here's the summary: \n";
submit_string += "Here\'s your value: " + line_misc[0]->text() + ".\n";
if (chk_art->isChecked())
submit_string += "Art major!";
msg_submit.setText(submit_string);
.
.
.
QObject::connect(&but_submit, SIGNAL(clicked()), &msg_submit, SLOT(exec()));
w->show();
return a.exec();
Everything that is not in the code here I have defined or initialized, and I don't have any warnings or errors when I run the code, all is well, everything is displayed, but it's like nothing is connected.
The message box (msg_submit) appears but the message is
Hello, here's the summary:
Here's your value: .
When I'm really expecting to see a number, or the art major comment as well if I have the checkbox (chk_art) checked, but I do not, unfortunately.
I've gone through the docs and tried variations, such as using a spinBox, and using the property function value() to just get the value and wrapping it in QString::number(), but no matter what I change the value to, it's like setValue property isn't called when I change the value, or the slot valueChanged() doesn't run either.
Am I doing something wrong?
you should update submit_string after click event emits.
Can try with lambda function
QObject::connect(&but_submit, &QPushButton::clicked,
[&line_misc, &chk_art](){
QMessageBox msg_submit;
QString submit_string = "Hello, here's the summary: \n";
submit_string += "Here\'s your value: " + line_misc[0]->text() + ".\n";
if (chk_art->isChecked())
submit_string += "Art major!";
msg_submit.setText(submit_string);
msg_submit.exec();
});

QListWidget::itemChanged signal triggered twice in qt

I have a QListWidget to store usernames, and I use this signal to detect if username is being changed:
connect(listWidget, &QListWidget::itemChanged, this, &MainWindow::changeUserName);
void MainWindow::changeUserName(QListWidgetItem *editItem)
{
qDebug() << "Name:" << editItem->text();
}
And this is how I make QListWidget editable in another function:
connect(listWidget, &QListWidget::itemDoubleClicked, this, &MainWindow::makeListEditable);
void MainWindow::makeListEditable()
{
QListWidgetItem *editItem = listWidget->currentItem();
editItem->setFlags(editItem->flags() | Qt::ItemIsEditable);
qDebug() << "Name edit";
}
But which confused me is, whenever I double clicked the list widget, the itemChanged signal will be triggered once, and when I input a new username, the signal will be triggered again. Why would this happen?
This is the debug output, when I double clicked the list, it says:
Name: "Testing name_1"
Name edit
after I entered a new name and hit the enter, it says:
Name: "Testing name_2" //a new name I changed to
And what if I only want a signal be triggered once whenever I input a new name and hit the enter, what should I do to achieve this?
Thanks
You can use the item delegate commitData signal, this way:
QObject::connect(listWidget->itemDelegate(), SIGNAL(commitData(QWidget*)), this, SLOT(dataCommited(QWidget*)));
the slot is like this:
void dataCommited(QWidget * w)
{
QString data = (static_cast<QLineEdit *>(w))->text();
//...
}
The signal will be emitted at the end of the editing (i.e. enter key pressed or focus lost etc.)
As #Rafalon said, calling setFlags calls your slot changeUserName, and the signal currentTextChanged is emitted when the current item changed, it is the same as currentItemChanged except it gives you the text instead of the item.
What you can do is, make your item editable as you instantiate it:
QListWidgetItem* pItem = new QListWidgetItem();
pItem->setText("Testing name_1");
pItem->setFlags(pItem->flags() | Qt::ItemIsEditable);
listWidget->addItem(pItem);
or you can activate/deactivate the connection when you need it:
void MainWindow::makeListEditable(QListWidgetItem *editItem)
{
editItem->setFlags(editItem->flags() | Qt::ItemIsEditable);
connect(ui->listWidget, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(changeUserName(QListWidgetItem *)));
qDebug() << "Name edit";
}
void MainWindow::changeUserName(QListWidgetItem *editItem)
{
qDebug() << "Name:" << editItem->text();
disconnect(ui->listWidget, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(changeUserName(QListWidgetItem *)));
}
but you will have to make another connection when the current element is not modified after a double click, maybe with the signal currentItemChanged.

children().count() of QGroupBox returns value more than expected

I'm testing the following point of Qt Documentation.
When you use a layout, you do not need to pass a parent when constructing the child widgets. The layout will automatically reparent the widgets (using QWidget::setParent()) so that they are children of the widget on which the layout is installed.
I created five QPushButtons and one QGroupbox using QDesigner. Then I add those buttons to QGridLayout and set that as layout of groupbox.
Then I tried to check the children of groupbox. But it shows 6 children instead of 5. One is empty and others are pushbuttons.
Here is my code.
QGridLayout *grd = new QGridLayout();
grd->addWidget(ui->pushButton,0,0);
grd->addWidget(ui->pushButton_2,0,1);
grd->addWidget(ui->pushButton_3,1,0,1,3);
grd->addWidget(ui->pushButton_4,2,0);
grd->addWidget(ui->pushButton_5,2,1);
ui->groupBox->setLayout(grd);
qDebug() << ui->groupBox->children().count();
foreach (QObject *button, ui->groupBox->children())
{
qDebug() << "obj name" << button->objectName();
QPushButton *push_button = qobject_cast<QPushButton *>(button) ;
if(push_button)
{
qDebug() << push_button->text();
}
}
Results I got.
6
obj name ""
obj name "pushButton"
"button 1"
obj name "pushButton_2"
"button 2"
obj name "pushButton_3"
"button 3"
obj name "pushButton_4"
"button 4"
obj name "pushButton_5"
"button 5"
Anyone can tell me why children().count() equal to 6 rather than 5?
Do the following:
qDebug() << "Class name:" << button->metaObject()->className();
and you will see one child is the QGridLayout
Or alternatively:
grd->setObjectName("GridLayout");
And the name should be displayed in the place of the empty string
What does this mean: the layout of the widget becomes a child of the widget.

How to change window title and central widget in Qt?

Hi, I have a problem with changing window title and central widget in Qt.
There is MainWindow:
class MainWindow : public QMainWindow
{
// (...)
QStackedWidget* widgets;
Quiz* widget1, *widget2;
}
and there is a class Quiz:
class Quiz : public QWidget
{
public slots:
void myClicked();
}
I wanted to change MainWindow title after clicking on button, which is a element of Quiz (and it is connected with slot myClicked).
void Quiz::myClicked()
{
static_cast<MainWindow>(parent).myFunction();
}
void MainWindow::myFunction()
{
widget2 = new Quiz(this,2);
widgets->addWidget(widget2);
std::cout<<"current wdgt: " << widgets->currentIndex() << std::endl; // shows: 0
widgets->setCurrentWidget(widget2);
std::cout<<"current wdgt " << widgets->currentIndex() << std::endl; // shows: 1
setWindowTitle("newTitle");
std::cout<<"Title is " << windowTitle().toStdString() << std::endl;
}
So widgets->currentIndex shows index of new widget but nothing is changed in my window. The same problem is with window title - method windowTitle() returns new title, but title on a titlebar is old. Why?
If I change title in Quiz::myClicked by:
parent->setWindowTitle("newTitle");
it works! Why it works how strange? Please help.
it works! Why it works how strange? Please help.
It is not strange. That is how the Qt API is designed. See the documentation for the explanation:
windowTitle : QString
This property holds the window title (caption).
This property only makes sense for top-level widgets, such as windows and dialogs.
Let us analyze the last sentence: your quiz is neither a QMainWindow, nor a QDialog, hence it cannot work. Windows titles only make sense for those based on the documentation. When you call it on the parent, it will work respectively since that is a QMainWindow.
The title bar shows the title of the MainWindow. Your Quiz widgets are "inside" the MainWindow, so their titles are not shown.
If you want to change the title bar text, you must call MainWindow::setWindowTitle().

How to get the role of a QPushButton created by a QDialogButtonBox?

I'm trying get all the button child widgets of a currently active window. The buttons were created through QDialogButtonBox. I'm trying to get the roles of each button so I can identify which button is the OK, CANCEL, or SAVE button. However I'm getting an error with the following code:
QWidget *pWin = QApplication::activeWindow();
QList<QPushButton *> allPButtons = pWin->findChildren<QPushButton *>();
QListIterator<QPushButton*> i(allPButtons);
while( i.hasNext() )
{
QDialogButtonBox *pButtonRole = new QDialogButtonBox();
QDialogButtonBox::ButtonRole role = pButtonRole->buttonRole(i.next());
qDebug() << "buttonRole: " << role << endl ;
//the value of role here is -1, which means it's an invalid role...
}
I'm getting a negative value when getting the button's role :(
Can somebody tell me what's wrong with the code?
You can't call a non-static method like that. You need to have the QDialogButtonBox variable and call that particular instance for buttonRole() to work.
QDialogButtonBox::ButtonRole role = myButtonBoxPtr->buttonRole(i.next());
You are creating a new empty QDialogButtonBox which has no idea about buttons in allPButtons list. Calling buttonRole() on them returns -1 (InvalidRole) because buttons are not in that button-box.
You must do as jkerian wrote and myButtonBoxPtr must point to the QDialogButtonBox which is already in your window.
You can try something like this (if you have one ButtonBox):
QDialogButtonBox *box = pWin->findChild<QDialogButtonBox *>();
foreach(QAbstractButton* button, box->buttons())
{ qDebug() << box->buttonRole(button); }