PDA

View Full Version : Cannot resize QTableView within a QWidget



ZikO
7th September 2012, 17:45
Hi,

I've got quite annoying problem. I've put a QTableView in a QWidget that works as an another window. The problem is that QTableView does not resize itself when I resize a window. Also, the window starts with its minimum geometry as if there was none of any layouts at all even though the QTableView is inside. So far, I tried to put QTableView in the one of the layouts: QGridLayout, QHBoxLayout etc. but it does not solve the problem. Am I doing something wrong here? I did not have such a problem before; all layouts with widgets worked great for me.

Just in case I put the part of the code that is responsible for opening the window.



void MyApp::showTabulatedEvents() {
const int maxRows = dbStoreToday.size();

upcomingEventsForToday(); // ustaw liste dbStoreToday

QWidget* tableWindow = new QWidget;
QVBoxLayout* tableLay = new QVBoxLayout(tableWindow);
tableWindow->setWindowTitle(trUtf8("Upcoming events for today"));
QTableView* tableView = new QTableView;
tableLay->addWidget(tableView);
tableView->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);

QStandardItemModel* model = new QStandardItemModel(5,dbStoreToday.size());
for(int row = 0; row < maxRows; ++row) {
model->setItem(row,0,new QStandardItem(dbStoreToday[row].imie));
model->setItem(row,1,new QStandardItem(dbStoreToday[row].nazwisko));
model->setItem(row,2,new QStandardItem(dbStoreToday[row].nazwa_wyd));
model->setItem(row,3,new QStandardItem(dbStoreToday[row].data_wyd.toString()));
model->setItem(row,4,new QStandardItem(tr("%1").arg(dbStoreToday[row].przypomnienie)));
}
tableView->setModel(model);
tableView->show();
tableWindow->show();
}


8194

maximebd
7th September 2012, 20:09
I tried the code you posted and it works fine, the table resizes with the window. Could you provide additional information? Qt version? Os version? Have you tried using the design editor in QCreator?

I used Qt 4.8.0 for MSVC2010.

ZikO
7th September 2012, 21:19
Hi Maximebd,

I am using QCreator but I have compiled Qt 4.8.2. I am quite surprised it's working for you. May I ask how you mean you have tried my code? I am asking because as you see this is only a function inside my fairly large project. This function is simply supposed to create another window (not the main window) with QTableView inside. Can you post the exact code you have written even if it's using my function. I would be grateful.

Thanks

maximebd
7th September 2012, 21:56
Here is the code I compiled and ran:



#include <QtGui>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QWidget* tableWindow = new QWidget();
QVBoxLayout* tableLay = new QVBoxLayout(tableWindow);
tableWindow->setWindowTitle("tralaa");
QTableView* tableView = new QTableView();
tableLay->addWidget(tableView);
tableView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

QStandardItemModel* model = new QStandardItemModel(5, 5);
for (int r = 0; r < 5; ++r)
{
for (int c = 0; c < 5; ++c)
{
model->setItem(r, c, new QStandardItem(QString::number(r*10 + c)));
}
}

tableView->setModel(model);
tableView->show();
tableWindow->show();

return a.exec();
}

ChrisW67
8th September 2012, 00:08
If something is not resizing correctly in Qt it is almost certainly because the layouts are broken, missing, or not applied.

You put the table widget into a layout but never apply the layout to the container widget (and maximebd does the same) so the two are not related in any automatic way. Here is a minimal example:


#include <QtGui>
#include <QDebug>

class Widget: public QWidget {
Q_OBJECT
public:
Widget(QWidget *p = 0): QWidget(p) {
QLabel *label = new QLabel("Just filling space for example", this);
QTableWidget *table = new QTableWidget(10, 5, this);

QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(label);
layout->addWidget(table);
setLayout(layout); // <<< the magic sauce
}
public slots:
private:
};

int main(int argc, char *argv[])
{
QApplication app(argc, argv);

Widget m;
m.show();
return app.exec();
}
#include "main.moc"

ZikO
8th September 2012, 01:35
Hi Chris

I tried maximebd's code and indeed I obtained essentially the same result but the window is larger by default. I also, to be honest, did try to put the line

tableWindow->setLayout(tableLay);
but it did not make any change. I am wondering why it did not make connection of this layout with the widget. Perhaps I need to make another class representing my window the way you have shown in your post. I'll try to follow this way but I am not sure if it's how it should be.

norobro
8th September 2012, 01:44
From the QWidget::setLayout() docs (http://qt-project.org/doc/qt-4.8/qwidget.html#setLayout):
An alternative to calling this function is to pass this widget to the layout's constructor. . . . which is what you have done.

You'll get the default minimum size for a widget unless you use QWidget::setMinimumSize() or subclass
QTableView, re-implement minimunSizeHint() and calculate the size. Check out the last post in this (http://www.qtcentre.org/threads/14764-QTableView-sizeHint%28%29-issues) thread. Note that the code posted there does not set limits on the width nor the height (a maximum minimum, if you will) so you could end up with a widget larger than your screen and no way to move around.

ZikO
8th September 2012, 02:38
@norobro
Hi norobro,

Thanks for this post. I will definitely try it.

----------
@Chris.
Unfortunately,

setLayout(tableLay);
is not working.
I did also try to inherit from QWidget, like I would make a single application, and add QTableView widget to it and set everything in roughly similar way to you in your last post. It also did not work. I have an impression I did everything like you did in your post. Yet, the result is exactly the same as before. There are two things that really are bothering me. First is that nothing I do cause any effect. The second is that I also set a title of that extra window with a table. Surprisingly, the title is the same as the title of my application application.

This is the code of the new class:

tableview.h


#ifndef TABLEVIEW_H
#define TABLEVIEW_H

#include <QWidget>
#include <QDialog>
#include <QVBoxLayout>
#include <QList>
#include <QTableView>
#include "../stworz_plik/rekord.h"

class TableView : public QDialog
{
Q_OBJECT

private:
QTableView* tableView;
QVBoxLayout* tableLay;

public:
explicit TableView(const QList<Wydarzenia::Rekord>& dbStoreToday, QObject *parent = 0);

signals:

public slots:

};

#endif // TABLEVIEW_H


and tableview.cpp


#include <QStandardItem>
#include <QStandardItemModel>
#include <QStringList>
#include <QStandardItem>
#include <QStandardItemModel>
#include <QStringList>
#include <QLabel>
#include "tableview.h"

TableView::TableView(const QList<Wydarzenia::Rekord> &dbStoreToday, QObject *parent)
: QWidget(parent) {

const int maxRows = dbStoreToday.size();

tableView = new QTableView(this);
tableView->setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);

tableLay = new QVBoxLayout(this);
tableLay->addWidget(tableView);
tableLay->addWidget(new QLabel("aaa",this));

QStandardItemModel* model = new QStandardItemModel(maxRows,5,this);
model->setHorizontalHeaderItem(0, new QStandardItem(trUtf8("Name")));
model->setHorizontalHeaderItem(1, new QStandardItem(trUtf8("Surname")));
model->setHorizontalHeaderItem(2, new QStandardItem(trUtf8("Event name")));
model->setHorizontalHeaderItem(3, new QStandardItem(trUtf8("Event date")));
model->setHorizontalHeaderItem(4, new QStandardItem(trUtf8("Remainder")));
for(int row = 0; row < maxRows; ++row) {
QStringList itemList;
itemList << dbStoreToday[row].imie << dbStoreToday[row].nazwisko << dbStoreToday[row].nazwa_wyd
<< dbStoreToday[row].data_wyd.toString() << tr("%1").arg(dbStoreToday[row].przypomnienie);
for(int col = 0; col < 5; ++col) {
QStandardItem* item = new QStandardItem(itemList[col]);
item->setEditable(false);
model->setItem(row,col,item);
}
}
tableView->setModel(model);
tableView->show();
setLayout(tableLay);
}


and the new function is as follows:


void MyApp::showTabulatedEvents() {
upcomingEventsForToday(); // ustaw liste dbStoreToday
TableView* tableView = new TableView(dbStoreToday,this);
tableView->setWindowTitle("Upcoming events");
tableView->show();
}

wysota
8th September 2012, 06:45
Could you please prepare a minimal compilable example reproducing the problem?

ZikO
8th September 2012, 13:35
Hello wysota,

Unfortunately, I could not reproduce this issue. I did prepare a simple application, let's call it "Simple Application" that creates a window with two buttons: "Show" and "Close". When "Show" is clicked, another window appears with a table. In "Simple Application", everything works as expected meaning the window opens with a default geometry (not with minimal size showing only a title bar). It only shows a part of a table but scroll bars are placed in the window not in the QTableView widget; that is, the whole table can be shown when the window is resized.

Obviously, as the function worked here, I tried to changed the main function in my application so that I could obtain the same effect. It did not work. I made one more try and copied everything. When I copied / pasted the whole content of MainWindow::showTable() from "Simple Application" to MyApp::showTabulatedEvents() in the main application and overwritten it, the QTableWidget was trimmed again and the issue still remains.
I am wondering what may cause this issue but this is far too much complex problem. Perhaps I can say more about application ...
The main application creates two timers, a system tray icon, a menu applied to the system tray icon, and connections. The first QTimer is just to check for an existing file once the event loop is in place. Once the timeout() is emitted, the timer is deleted. Another timer triggers a signal that is connected to a function which shows information in a balloon. The application creates a trayIconMenu, a few actions, and connect SIGNALs of each action triggered() function with SLOTs. Because some information are too long I tried to let user see tabulated information; that is, one of the actions from menu makes MyApp::showTabulatedEvents() call that should show information in table.
I was also wondering if I should make a simple application with system tray icon but that would take a bit more space here.

EDIT: One more thing. The program has its main window that can be used to make settings. At the moment, it only set up the time per which notification appears in system tray periodically. The main window is closed by default. I am wondering if this may cause the problem because if the main window is closed, then another window becomes the main window.


main.cpp in Simple Application


#include <QtGui>
#include "mainwindow.h"

int main(int argc, char* argv[]) {
QApplication app(argc,argv);

MainWindow mwin;
mwin.setWindowTitle("The main window's title");
mwin.show();

return app.exec();
}


mainwindow.h in Simple Application



#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtGui>

class MainWindow : public QWidget {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
signals:
public slots:
void showTable();
};

#endif // MAINWINDOW_H


mainwindow.cpp in Simple Application


#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
: QWidget(parent) {

QHBoxLayout* hBoxLay = new QHBoxLayout;
QPushButton* showButton = new QPushButton(tr("Show"));
QPushButton* closeButton = new QPushButton(tr("Close"));
hBoxLay->addWidget(showButton);
hBoxLay->addWidget(closeButton);
setLayout(hBoxLay);

connect(closeButton,SIGNAL(clicked()),qApp,SLOT(qu it()));
connect(showButton,SIGNAL(clicked()),this,SLOT(sho wTable()));
}

void MainWindow::showTable() {
QWidget* tableWindow = new QWidget;
tableWindow->setWindowTitle("Another title");

QGridLayout* tableLay = new QGridLayout(tableWindow);
QTableView* tableView = new QTableView;
tableLay->addWidget(tableView);

tableView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QStandardItemModel* model = new QStandardItemModel(5, 5, tableWindow);
for (int row = 0; row < 5; ++row) {
for (int col = 0; col < 5; ++col) {
QStandardItem* item = new QStandardItem(tr("Row: %1, Col: %2").arg(row).arg(col));
item->setEditable(false);
model->setItem(row, col, item);
}
}
tableView->setModel(model);
tableView->show();

tableWindow->setLayout(tableLay);
tableWindow->show();
}

ZikO
8th September 2012, 22:22
Ok,

I am devastated :( I cannot understand the behaviour of the Qt.

There was no way to make QTableView works so I created a new project and just in case tested the QTableView within a new window whether it works before anything else. I put just a testing title "Another title" and some arbitrary coordinates 400,300. Because QTableView was rendered correctly, I copied pasted everything into new project. Then, I tried to change the title back and increase size of the window with QTableView but I cannot. The issue is exactly the same with that difference that now I have setLayout applied as it was applied first time and the ir works. However, I cannot change title, coordinates, size, nothing. This looks to me like Qt does not refresh information even between compilations. I did try to Clean All and rebuild app, I also removed all Makefile(s) but it does not change the window parameters. What else can I do? This issue is really strange.

Is there any place that Qt keeps QWidget information?

Added after 17 minutes:

I removed all files such as *.rcc, *.qrc, and *.rc and I can finally see the app changes between compilations. I have also removed completely Debug folder. I cannot say what has helped. It's a strange issue. I still don't know whether I caused that myself or whether it is a bug.

wysota
9th September 2012, 11:01
This looks to me like Qt does not refresh information even between compilations.

Qt is not a vicious man pulling strings to ruin your application. It is an application development framework, a simple set of libraries. It does not do anything to your compilation. If rebuilding the project from scratch doesn't help to reflect changes you make in a file then the most obvious reason is that you are changing the wrong file.

If you can't reproduce your problem with a simple example, then apparently the problem is not in the part of code illustrated by the example which implies that you are probably looking for the bug in the wrong place.

ZikO
9th September 2012, 16:08
Because I am a beginner, I really cannot precisely indicate the issue. I wish I could. However, I did my best to provide all my observations and results.
It's definitely the last thing I would discuss or argue with someone with strong expertise in this area. However, what I am saying is that the issue was repeated in two cases when I rebuild the application. I did not blindly copy / paste everything. As I said I was testing new app progressively. Whether this matter is taken seriously or not, I know where I should search the issue if this happens again. I explained when it started working. I cannot however be certain and answer if changes a QWidget object parameters should take the effect after next compilation always. I used a Qt library and I changed its parameters so IMO it should have something to do with Qt. I really believe that changes should take effect immediately after compilation. And this is why I wrote two last posts.

wysota
9th September 2012, 17:12
If you change a file containing Qt code and start the build process, "Qt" doesn't "touch" your file, the C++ compiler does. It is completely no difference whether your project uses Qt or not. If changes made in the file are not reflected then it means the file was not recompiled or that what you see doesn't come from the file you thought it comes from. Sometimes people have two files with the same name and simply change the wrong one or they have two copies of code producing some result in their project and they are changing one but then looking at results of the other. To verify whether any of these is the case, the simplest way is to make a syntax error in the file. If the project builds afterwards then it means the compiler didn't even parse the source file (again, Qt having nothing to do with that as it is only used runtime).

The code in your initial post looks correct and should provide a valid layout setup.

ZikO
9th September 2012, 20:05
To verify whether any of these is the case, the simplest way is to make a syntax error in the file. If the project builds afterwards then it means the compiler didn't even parse the source file (again, Qt having nothing to do with that as it is only used runtime).

The code in your initial post looks correct and should provide a valid layout setup.

Hello,

Thank you for this post. I appreciate the effort in providing the explanation and I am happy with that clue; it is actually very practical one. I'll do it next time when that issue occurs again, if it occurs again.

decipher
11th September 2012, 07:26
in qtcreator... choose frame and drop in form..right click on the form and choose set layout as vertical and drop ur tableview in that frame. right click in that frame and choose layout as horizontal... it will resize automatically...let me know how it works