How to make a QMdiArea subwindow widget non-resizeable? - c++

So the non-QMdiArea version of my code,
MyWidget::MyWidget(QWidget* parent)
{
...
layout()->setSizeConstraint( QLayout::SetFixedSize );
}
MainWindow::MainWindow(...)
{
...
MyWidget* wgt = new MyWidget(NULL);
wgt->show();
}
works just fine and produces a widget that the user can't resize. But when the MainWindow code is replaced with
MainWindow::MainWindow(...)
{
...
MyWidget* wgt = new MyWidget(ui->mdiArea); //Or MyWidget(NULL), same result
ui->mdiArea->addSubWindow(wgt);
}
the window, now within the QMdiArea, is resizeable. It doesn't seem to be an issue of Qt::WindowFlags, they don't handle resize policy. Surely there is a way to do this? NB I cant use something like setFixedSize(ht, wd) since the size of the widget can change programmatically (subwidgets are added and removed). But the user should not be able to resize it.

Even though MyWidget is not resizeable, when you call:
ui->mdiArea->addSubWindow(wgt);
The widget is put in a QMdiSubWindow which is resizeable. All you have to do is get the window that's created and fix its size:
QMdiSubWindow* subWindow = ui->mdiArea->addSubWindow(wgt);
subWindow->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
This should work, but I haven't tried this code myself.
EDIT: well... apparently that doesn't fix the size. :(

The following worked for me:
MyWidget* wgt = new MyWidget(ui->mdiArea);
QMdiSubWindow* subWindow = ui->mdiArea->addSubWindow(wgt);
subWindow->setFixedSize(wgt->size());
wgt->show();

Related

How to fix the size of MDI Subwindow in Qt

I'm creating a Desktop Application in Qt and I'm showing subwindow inside the MDI Area. I have the problem that in the size of subwindow adjusts every time I open my code in the other monitor.
My goal is to fix the size of subwindow and make it parent size. Hope you understand my problem.
I'm using this code to change the size and showing the subwindow in mdi area
Subwindow1 = new QMdiSubWindow(mdiArea);
QQuickWidget* widget2 = new QQuickWidget(Map);
widget2->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget2->setSource(QUrl("qrc:/subwindow1.qml"));
widget2->show();
Subwindow1->setWidget(widget2);
Subwindow1->resize(700,640);
Subwindow1->setWindowTitle("Subwindow 1");
Subwindow1->setAttribute(Qt::WA_DeleteOnClose,false);
Subwindow1->setWindowFlag(Qt::FramelessWindowHint);
Subwindow1->addSubWindow(Subwindow1);
mdiArea->setActiveSubWindow(Subwindow1);
Subwindow1->show();
Subwindow2 = new QMdiSubWindow(mdiArea);
QQuickWidget* widget3 = new QQuickWidget(Camera1);
widget3->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget3->setSource(QUrl("qrc:/subwindow2.qml"));
widget3->show();
Subwindow2->setWidget(widget3);
Subwindow2->resize(304,270);
Subwindow2->setWindowTitle("Subwindow 2");
Subwindow2->setAttribute(Qt::WA_DeleteOnClose,false);
Subwindow2->setWindowFlag(Qt::FramelessWindowHint);
mdiArea->addSubWindow(Subwindow2);
mdiArea->setActiveSubWindow(Subwindow2);
Subwindow2->show();
Subwindow3 = new QMdiSubWindow(mdiArea);
QQuickWidget* widget4 = new QQuickWidget(Camera2);
widget4->setResizeMode(QQuickWidget::SizeRootObjectToView);
widget4->setSource(QUrl("qrc:/subwindow3.qml"));
widget4->show();
Subwindow3->setWidget(widget4);
Subwindow3->resize(304,270);
Subwindow3->setWindowTitle("Subwindow 3");
Subwindow3->setAttribute(Qt::WA_DeleteOnClose,false);
Subwindow3->setWindowFlag(Qt::FramelessWindowHint);
mdiArea->addSubWindow(Subwindow3);
mdiArea->setActiveSubWindow(Subwindow3);
Subwindow3->show();
For example :
You have Subwindow1 with (700,640)
The code is : Subwindow1->setFixedSize(new QSize(700,640))
Hope it help !
https://doc.qt.io/qt-5/qwidget.html#setFixedSize

The inferior stopped because it received signal from the Operating System error on resizable scrollarea

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.

Memoryleak with QListWidget addItem() + setItemWidget()

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);

Qt QScrollArea autoscroll

I'm having problems with QLabel and QScrollArea. I'm trying to make QScrollArea to scroll automatically, but can't find any information about it..
Firstly, I'm using QLabel inside QScrollArea, then QLineEdit outside from QScrollArea. When I type text in QLineEdit, it writes to QLabel and the new line. Whenever it reaches to end of area, QScrollArea doesn't scroll automatically.. How can I do that?
Thank you.
Can't you use QLineEdit itself instead of Qlabel(if u are using only text)?, so that you dont have to use QScrollArea also.
[edit]
What if you set the verticalSlider position to Label->height()
void MainWindow::on_lineEdit_returnPressed()
{
ui->label->setText(ui->label->text() + ui->lineEdit->text() + "\n");
ui->ScrollArea->verticalScrollBar()->setSliderPosition(label->height())
}
Take a look at this example: http://qt-project.org/forums/viewthread/23790/
Without to see your code that is difficult to be more precise ...
[EDITED] Try this:
void MainWindow::on_lineEdit_returnPressed()
{
ui->label->setText(ui->label->text() + ui->lineEdit->text() + "\n");
ui->lineEdit->moveCursor (QTextCursor::Start) ;
ui->lineEdit->ensureCursorVisible() ;
...
}

Qt - There is a bug in QPropertyAnimation?

I face a very serious situation. By writing this question I hope that really professionals will express their opinion regarding to the problem I am going to describe. I have reported a bug in https://bugreports.qt.io/ :
I have created QPropertyAnimation for maximumWidth property of QTextEdit and it does not work (it immediately changes state from starting state to the end state), though it works for minimumWidth property.
Please see the attached code.
And have attached .h and .cpp files. See those files here (files are named new.h and new.cpp).
And I got the follwing response:
MaximumWidth is not the property you want to animate. It holds the maximum width that the widget can have, it's related to layouting and so on. Changing the maximumWidth (as well as the minimumWidth) does not necessarily trigger a relayout and repaint. You should animate the size.
Please explain me whether it is a bug or no? Please tell me how the minimumWith property is being animated but when it concerns to the maximumWidth property, then I should not work and that is OK? I just don't get their point... Please explain.
P.S. I have written this code because I wanted to close by animation the right QTextEdit and be sure that when I resize the main window, where the button and two QTextEdit are, the closed QTextEdit does not being restored.
Did you check the actual value of maximumWidth? You don't seem to set a specific maximumWidth in your code.
The default value for maximumWidth is 16777215, and you set a duration of 1 msec. for the closing animation. Fading from 16777215 to 3 in 1 msec. would look like "instant", I guess.
I don't think it is a bug; I'd call it "undefined behavior". That means that if you try to animate minimumWidth, nobody can tell you for sure what is supposed to happen, and maybe the code has some optimizations or corner cases where sometimes it works, others it doesn't.
Anyway, minimumWidth and maximumWidth aren't supposed to be used to define what the size of a QWidget is, only what it must not exceed; i.e. they weren't designed to do what you are trying to do, so it can be called a bug. If you want to animate, you have to use a deterministic approach, which in this case is using the geometry property.
This is not a bug, the response you got from the bug report pretty well explains the problem with your code and a solution.
Dear Sofahamster I have changed my code to the code below and it works fine. Thanks for your hint!
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 );
}