I have created a QMainWindow which could create one or more QMdiSubWindows, and the following method is the responsible for creating the sub-windows:
void PSubWindow::newFile(){
static ushort newFileCounter = 1;
this->mdiareaContainer = this->mainWindow->findChild<QMdiArea*>("mdiArea");
QMdiSubWindow *window = new QMdiSubWindow();
window->setAttribute(Qt::WA_DeleteOnClose, true);
window->setWidget(new QPlainTextEdit);
this->subWindow = mdiareaContainer->addSubWindow(window);
QString FileTitle = "Untitled " + QString::number(newFileCounter++);
this->subWindow->setWindowTitle(FileTitle);
this->subWindow->show();
this->mdiareaContainer->setViewMode(QMdiArea::TabbedView);
this->mdiareaContainer->setTabsClosable(true);
this->mdiareaContainer->setTabsMovable(true);
this->tabs = mdiareaContainer->findChild<QTabBar*>();
this->tabs->setExpanding(false);
QObject::connect(this->tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(on_subWindow_tabCloseRequested(int)), Qt::UniqueConnection);
}
As you seen in the code I have created a signal for closing which one of them.
void PSubWindow::on_subWindow_tabCloseRequested(int index) {
QList<QMdiSubWindow*> sub = this->mdiareaContainer->subWindowList();
qDebug()<< sub[index];
}
Always when closing the last window appear an error message during runtime, the message says:
How can I solve that problem?
Check if index is smaller than sub.size(); the list will be empty because the last window has been closed, but index is probably still 0.
When you remove the tab, the window is removed, so that position no longer exists in the list.
Related
I have a QScrollArea inside QTabWidget and I have a QWidget beside my QTabWidget. I want QScrollArea to be resized when my main window is resized, so I have made this code like this:
void frmSummaryContact::on_btnAddNewContact_clicked()
{
MainWindow *mnWindow = qobject_cast<MainWindow *>(this->parent()->parent()->parent()->parent()->parent()->parent());
QTabWidget *tbWidget = qobject_cast<QTabWidget *>(this->parent()->parent()->parent()->parent());
frmDetailContact *frm = new frmDetailContact(mnWindow, "input", -1, mnWindow->rightPane());
QScrollArea *scrlForm = new QScrollArea;
scrlForm->setWidgetResizable(true);
scrlForm->setWidget(frm);
mnWindow->AddNewTab(tbWidget, scrlForm, "Add Contact");
}
my QTabWidget is in different form, so I cast it with qobject_cast. Meanwhile in another form, I have a toogle button to hide QWidget so my QTabWidget get wider. So in that form I have a code like this:
void frmDetailContactToggle::on_btnSearch_clicked()
{
MainWindow *mnWindow = qobject_cast<MainWindow *>(this->parent()->parent()->parent());
QLayoutItem *child;
while ((child = mnWindow->rightPane()->layout()->takeAt(0)) != 0)
child->widget()->setVisible(false);
mnWindow->rightPane()->setVisible(false);
QScrollArea *scrlContent = qobject_cast<QScrollArea *>(mnWindow->tabContentWidget()->currentWidget());
scrlContent->setWidgetResizable(false);
mnWindow->tabContentWidget()->setGeometry(mnWindow->tabContentWidget()->x(), mnWindow->tabContentWidget()->y(), m_width - mnWindow->tabContentWidget()->x() - 10, mnWindow->tabContentWidget()->height());
scrlContent->setWidgetResizable(true);
m_showRightPane = false;
}
I have realized that I can't change the geometry when WidgetResizable is true. It showed "The inferior stopped because it received signal from the Operating System" error. So I thought about making it false, changing the geometry, and making it true again. But when I want to make it true, I encounter the same error. Could anyone please help me to solve my problem?
if your program used uninitialized pointers,that may causes SIGSEGV.
I have a custom QWidget class called VideoWidget. Its source file looks something like this:
VideoWidget::VideoWidget(QWidget *parent, string test) :
QWidget(parent)
{
pathname=test;
QLabel *label= new QLabel(pathname.c_str(), this);
//...
}
string VideoWidget::getFilePath(){
return pathname;
}
In my MainWindow class I add the VideoWidget to a QListWidget through looping through a xml file and getting the string argument from that file like this:
QDomNode node = rootXML.firstChild();
while( !node.isNull() )
{
if( node.isElement() )
{
QDomElement element = node.toElement();
VideoWidget* mytest = new VideoWidget(this, element.attribute( "Pathname", "not set").toStdString());
QListWidgetItem* item = new QListWidgetItem;
item->setSizeHint(QSize(150,100));
ui->myList->addItem(item);
ui->myList->setItemWidget(item,mytest);
}
node = node.nextSibling();
}
This correctly fills my QListWidget with the VideoWidget where all the labels have a different value.
Now I'd like to get the pathname variable everytime I doubleclick on a item in the QListWidget like this:
connect(ui->myList,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(playClip(QModelIndex)));
void MainWindow::playClip(QModelIndex index){
QListWidgetItem* item = ui->myList->itemAt(0,index.row());
VideoWidget* widget = dynamic_cast<VideoWidget*>(ui->myList->itemWidget(item));
cout << widget->getFilePath() << endl;
}
My problem is that widget->getFilePath() always returns the same value for every clicked widget. It is the value of the first time I set pathname=test;. What am I missing here?
This is probably mistake:
QListWidgetItem* item = ui->myList->itemAt(0,index.row());
Method "itemAt" takes x and y coordinates, not indexes. Use "takeItem" instead.
Next thing I want to say is that this part:
ui->myList->itemWidget(item)
is useless. You can convert "item" directly.
And last - use qobject_cast since you use Qt. And never use dynamic_case (especially when you anyway do not check result against NULL).
When I press a key there shall be a query to an engine. The results get put into a QListWidget by adding an item and setting the widget. Somehow this causes a massive memory overflow and even crashed my machine. But I dont get the error. Does clear() not delete the items passed to the QListWidget and the widgets set by setItemWidget(). I even tried to delete them on my own (comment), but still got a memoryleak. The error is in the if (!results.empty())-block, I guess, since commenting it out plugs the memoryleak.
void Widget::onTextEdited(const QString & text)
{
// QListWidgetItem * takenItem;
// while (takenItem = _results->takeItem(0)){
// delete _results->itemWidget(takenItem);
// delete takenItem;
// }
_results->clear(); _results->hide();
if (!text.isEmpty())
{
const std::vector<const Items::AbstractItem *> results = _engine.request(text);
if (!results.empty())
{
for (auto i : results){
QListWidgetItem *lwi = new QListWidgetItem;
_results->addItem(lwi);
ListItemWidget *w = new ListItemWidget;
w->setName(i->name());
w->setTooltip(i->path());
_results->setItemWidget(lwi, w);
}
_results->setFixedHeight(std::min(5,_results->count()) * 48); // TODO
_results->show();
}
}
this->adjustSize();
}
You should definitely use a memory leak detection tool instead of guessing around :)
UPDATE: clear() only deletes items but does not delete the widgets belonging to it. The widgets will be deleted if the QListWidget is deleted.
clear() does delete items and widgets belonging to it. And you mentioned that commenting out if(!results.empty()) solved the problem. I don't see any problem in the setItemWidget part. So I think the problem lies somewhere else, maybe ListItemWidget. How about you try replacing ListItemWidget with QLabel and see what happens. Eg:
QListWidgetItem *lwi = new QListWidgetItem;
_results->addItem(lwi);
//ListItemWidget *w = new ListItemWidget;
//w->setName(i->name());
//w->setTooltip(i->path());
QLabel *w = new QLabel;
w->setText("Hello");
_results->setItemWidget(lwi, w);
In my project, I have a listWidget. When the user clicks an item in the list, it loads this:
void BlockSelect::on_blockList_clicked(const QModelIndex &index)
{
QString blockListName;
QString temp_hex;
QString temp_hex2;
int temp_int;
QListWidgetItem *newitem = ui->blockList->currentItem();
blockListName = newitem->text();
temp_hex = blockListName.mid(0, blockListName.indexOf(" "));
if(temp_hex.indexOf(":") == -1)
{
temp_int = temp_hex.toInt();
ui->blockIdIn->setValue(temp_int);
ui->damageIdIn = 0;
}
else
{
temp_hex2 = temp_hex.mid(temp_hex.indexOf(":")+1, temp_hex.length()-(temp_hex.indexOf(":")+1));
temp_hex = temp_hex.mid(0, temp_hex.indexOf(":"));
temp_int = temp_hex.toInt();
ui->blockIdIn->setValue(temp_int);
temp_int = temp_hex2.toInt();
ui->damageIdIn->setValue(temp_int);
}
}
Most of this is just string manipulation. (You don't have need to study this syntax or anything)
My problem is, when the user clicks on another list item quickly (Before this current process is finished) the program crashes. Is there any way to allow fast clicks (multiple processes at once) or maybe an alternative solution?
Thanks for your time :)
I hope that you execute all this code in the GUI thread. If so, then there will be no problem - if your code were correct (it isn't). There is no such thing as the "process" that you mention in your question. The clicks are handled by a slot, and they are invoked from an event handler within the list. This is not supposed to crash, and the clicks will be handled in a serialized fashion - one after another.
Here's the bug: Why do you reset the value of an allocated UI pointer element to zero?
ui->damageIdIn = 0;
This is nonsense. Maybe you mean to ui->damageIdIn->setValue(0) or ui->damageIdIn->hide(). You then proceed to use this zero value in
ui->damageIdIn->setValue(temp_int);
and it crashes.
You may also have bugs in other places in your code.
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); }