Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Qt
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.60/42: Рейтинг темы: голосов - 42, средняя оценка - 4.60
Speedy Gonzales
6 / 6 / 2
Регистрация: 22.10.2010
Сообщений: 82
#1

Программное добавление элемента на форму

25.11.2012, 18:17. Просмотров 7600. Ответов 21
Метки нет (Все метки)

Доброе всем со-товарищам!
Перехожу на Qt с C# и возникло пару проблем с динамическим добавлением на форму элементов управления. На шарпе все было просто, создаем элемент класса, добавляем его хар-ки и через координаты размещаем его на Form Все очень хорошо работает, что через дизайнер, что чисто программное размещение к уже имеющимся элементам. В Qt возникла сложность с этим. В дизайнере создал форму:

http://s6.image1.org/images/2012/11/...6e91a1e79f.jpg
потом я задаю функцию, при нажатии кнопку должно, допустим, получится такое:

http://s6.image1.org/images/2012/11/...bc06c879d3.jpg
пробовал сделать похожим, как на шарпе способом, но New_GB с NewButton растягиваются на всю форму и никакие setGeometry не помогают. Сделайте маленький ЛикБез по этому вопросу, пожалуйста. Наверное многим это бы пригодилось бы.
Заранее спасибо.
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void MainWindow::on_pushButton_clicked()
{
    qDebug()<<centralWidget()->children(); 
    newFun();
}
 
void MainWindow::newFun()
{
    QGridLayout *grid = new QGridLayout;
    QGroupBox *gb = new QGroupBox(tr("New GroupBox"));
    gb->setGeometry(90, 100, 100, 100);
    QPushButton *pb=new QPushButton(tr("NewButton"));
    pb->setGeometry(20, 20, 50, 50);
    grid->addWidget(gb);
 
    
    ui->centralWidget->setLayout(grid);
    
}
без
C++ (Qt)
1
QGridLayout *grid = new QGridLayout;
вообще ничего не хотелось вставляться. Думал, что можно просто добавлять в centralWidget любые элементы, но мне сказали - ФИГ...

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
void MainWindow::newFun()
{
    QGroupBox *gb = new QGroupBox(tr("New GroupBox"));
    gb->setGeometry(90, 100, 100, 100);
    QPushButton *pb=new QPushButton(tr("NewButton"));
    pb->setGeometry(20, 20, 50, 50);
 
    gb->setLayout(pb);
    
    ui->centralWidget->setLayout(gb);
    
}


так нельзя.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.11.2012, 18:17
Ответы с готовыми решениями:

Добавление картинки на форму
Тект в qlabel добавляется, а картинка нет. Что я делаю не так? ...

Добавление картинок в форму
Имхо простейшая задача, но почему-то не смог сам найти решение. Как добавить...

Добавление виджетов на форму QtDesigner
Здравствуйте. Помогите разобраться пожалуйста. Скачал QT, создал проект, но в...

Qt, добавление на существующую форму (не динамически)
есть Qtшная форма. давно созданная, к ней есть её хеддер(как я понимаю...

Добавление данных на форму с текстового файла
Здравствуйте, возникла необходимость сделать тоже самое что и в этой теме...

21
KeyGen
384 / 291 / 21
Регистрация: 07.08.2011
Сообщений: 790
Записей в блоге: 1
26.11.2012, 00:50 #2
Могу посоветовать книгу: Макс Шлее, Qt4 Профессиональное программирование на С++. Читай такие вопросы отпадут.
1
Speedy Gonzales
6 / 6 / 2
Регистрация: 22.10.2010
Сообщений: 82
26.11.2012, 10:51  [ТС] #3
Спасибо большое, я купил его книгу и поизучал. Там используется система виджетов, а хотелось бы понять как можно работать без них. В дизайнере можно просто размещать элементы управления, так почему же нельзя их так же размещать программно?
0
Чистый
Автор FAQ
2713 / 1409 / 89
Регистрация: 08.09.2011
Сообщений: 3,741
Записей в блоге: 1
26.11.2012, 10:58 #4
а вы и размещаете виджеты, т.е. элементы управления это и есть виджеты
0
Dmitriy_M
1422 / 1303 / 130
Регистрация: 20.03.2009
Сообщений: 4,654
Записей в блоге: 11
26.11.2012, 10:58 #5
Цитата Сообщение от Speedy Gonzales Посмотреть сообщение
Спасибо большое, я купил его книгу и поизучал. Там используется система виджетов, а хотелось бы понять как можно работать без них. В дизайнере можно просто размещать элементы управления, так почему же нельзя их так же размещать программно?
Можно, но почти никто так не делает.
1
Speedy Gonzales
6 / 6 / 2
Регистрация: 22.10.2010
Сообщений: 82
26.11.2012, 11:56  [ТС] #6
Я пытаюсь сделать элементарное действие, через кнопку добавить groupBox на форму в определенном месте, а в итоге этот groupBox занимает все пространство centralWidget. Хотя я задавал координаты и размеры groupBox.
0
Dmitriy_M
1422 / 1303 / 130
Регистрация: 20.03.2009
Сообщений: 4,654
Записей в блоге: 11
26.11.2012, 12:01 #7
Цитата Сообщение от Speedy Gonzales Посмотреть сообщение
Я пытаюсь сделать элементарное действие, через кнопку добавить groupBox на форму в определенном месте, а в итоге этот groupBox занимает все пространство centralWidget. Хотя я задавал координаты и размеры groupBox.
Не надо было запихивать в компоновщик.
В качестве парента, для QGroupBox указываешь centralWidget и получаешь то что нужно.

Возможно проще создать объект за ранее и скрыть, а по нажатию сделать объект видимым.
1
_SASA_
134 / 138 / 7
Регистрация: 22.08.2011
Сообщений: 484
26.11.2012, 13:53 #8
Здравствуйте!
Dmitriy_M все правильно написал =
уберите Layout, если не хотите растягиваний,
а родителя можно задать и так:
C++ (Qt)
1
2
3
4
5
6
7
8
... // this - тот родитель внутри которого пишите...
QGroupBox *gb = new QGroupBox(tr("New GroupBox"),this);
gb->setGeometry(90, 100, 100, 100);
gb->show();
QPushButton *pb=new QPushButton(tr("NewButton"),this);
pb->setGeometry(20, 20, 50, 50);
pb->show();
...
Удачи!!
2
Speedy Gonzales
6 / 6 / 2
Регистрация: 22.10.2010
Сообщений: 82
26.11.2012, 17:35  [ТС] #9
Спасибо большое, оказалось просто нужно использовать
C++ (Qt)
1
Show();
Но так я просто смогу отобразить элемент в centralWidget и при этом он не растягивается по всей форме. А вот можно сделать, чтобы он был наследником centralWidget? И так же занимал любую позицию на форме (через setGeometry() )?

Догадался, что можно так

C++ (Qt)
1
gb->setParent(ui->centralWidget);
Добавлено через 3 часа 4 минуты
А еще не подскажите к получить все имена элементов формы

C++ (Qt)
1
2
for (var=0 var > ui->centralWidget->children().count() ++var)
ui->centralWidget->children.at(var);
Так я могу получить все элементы, а как можно получить только их name?
0
HomeR_J_SimpsoN
59 / 59 / 8
Регистрация: 15.10.2010
Сообщений: 356
26.11.2012, 21:30 #10
Цитата Сообщение от Speedy Gonzales Посмотреть сообщение
к получить все имена элементов формы
http://doc.qt.digia.com/qt/qobject.html#children
Любой виджет - наследник QObject. Соответственно ф-ией children() можно получить всех потомков любого виджета. Результат ф-ии -- QList< QObject * >.
Соответственно, перебирая контейнер поэлементно, можно получить доступ к любому объекту, являющемуся дочерним к данному.
Далее ф-ией QObject::objectName() получаем его имя.
1
Speedy Gonzales
6 / 6 / 2
Регистрация: 22.10.2010
Сообщений: 82
27.11.2012, 07:45  [ТС] #11
большое спасибо!
а можно немного расширить ответ и небольшой пример кода дать с QList< QObject * >
0
HomeR_J_SimpsoN
59 / 59 / 8
Регистрация: 15.10.2010
Сообщений: 356
27.11.2012, 12:14 #12
Цитата Сообщение от Speedy Gonzales Посмотреть сообщение
небольшой пример кода
Лично я не вижу особого смысла в переборе каждого компонента формы.
Проще запрашивать у родителя определенные виджеты, зная их тип и имя.

Например, был создан виджет с парой кнопок:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
QWidget *w = new QWidget(this);
w->setObjectName("containerWidget");
w->setLayout(new QVBoxLayout);
 
QPushButton *btn = new QPushButton;
btn->setText(tr("Кнопка 1");
btn->setObjectName("btn1");
w->layout()->addWidget(btn);
 
btn = new QPushButton;
btn->setText(tr("Кнопка 2");
btn->setObjectName("btn2");
w->layout()->addWidget(btn);
Теперь где то еще найдем эти кнопки и изменим их текст:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Попробуем сначала взять весь список сыновей для Виджета containerWidget
// Но для начала его надо тоже найти
QWidget *w = this->findChild< QWidget * >("containerWidget");
 
QObjectList l = w->children();
foreach (QObject *o, l)
{
    if (o->metaObject()->className() == "QPushButton")
    {
        QPushButton *b = static_cast< QPushButton * >(o);
        b->setText(tr("Текст изменен"));
    }
}
// Теперь просто найдем все кнопки с нашего виджета:
QList< QPushButton * > l1 = w->findChildren< QPushButton * >();
foreach (QPushButton *b, l1)
{
    if (b->objectName() == "btn1")
        b->setText(tr("Кнопка 1, текст изменен"));
    else if (b->objectName() == "btn2")
        b->setText(tr("Кнопка 2, текст изменен"));
}
 
// Теперь просто возьмем конкретную кнопку с виджета и изменим ее текст
w->findChild< QPushButton * >("btn1")->setText(tr("Нашли кнопку 1"));
w->findChild< QPushButton * >("btn2")->setText(tr("Нашли кнопку 2"));
0
Dmitriy_M
1422 / 1303 / 130
Регистрация: 20.03.2009
Сообщений: 4,654
Записей в блоге: 11
27.11.2012, 12:24 #13
Кликните здесь для просмотра всего текста
Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
Лично я не вижу особого смысла в переборе каждого компонента формы.
Проще запрашивать у родителя определенные виджеты, зная их тип и имя.

Например, был создан виджет с парой кнопок:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
QWidget *w = new QWidget(this);
w->setObjectName("containerWidget");
w->setLayout(new QVBoxLayout);
 
QPushButton *btn = new QPushButton;
btn->setText(tr("Кнопка 1");
btn->setObjectName("btn1");
w->layout()->addWidget(btn);
 
btn = new QPushButton;
btn->setText(tr("Кнопка 2");
btn->setObjectName("btn2");
w->layout()->addWidget(btn);
Теперь где то еще найдем эти кнопки и изменим их текст:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Попробуем сначала взять весь список сыновей для Виджета containerWidget
// Но для начала его надо тоже найти
QWidget *w = this->findChild< QWidget * >("containerWidget");
 
QObjectList l = w->children();
foreach (QObject *o, l)
{
    if (o->metaObject()->className() == "QPushButton")
    {
        QPushButton *b = static_cast< QPushButton * >(o);
        b->setText(tr("Текст изменен"));
    }
}
// Теперь просто найдем все кнопки с нашего виджета:
QList< QPushButton * > l1 = w->findChildren< QPushButton * >();
foreach (QPushButton *b, l1)
{
    if (b->objectName() == "btn1")
        b->setText(tr("Кнопка 1, текст изменен"));
    else if (b->objectName() == "btn2")
        b->setText(tr("Кнопка 2, текст изменен"));
}
 
// Теперь просто возьмем конкретную кнопку с виджета и изменим ее текст
w->findChild< QPushButton * >("btn1")->setText(tr("Нашли кнопку 1"));
w->findChild< QPushButton * >("btn2")->setText(tr("Нашли кнопку 2"));


А не проще ли хранить указатели на созданные виджеты в QMap<QString, QWidget*>?
0
HomeR_J_SimpsoN
59 / 59 / 8
Регистрация: 15.10.2010
Сообщений: 356
27.11.2012, 12:33 #14
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
А не проще ли хранить указатели на созданные виджеты в QMap<QString, QWidget*>?
Мне проще так.
И работает быстрее чем сравнивать по хэш таблице строки.

Добавлено через 5 минут
Да и зачем мудрить свой огород, если есть отличные стандартные средства.
0
Dmitriy_M
1422 / 1303 / 130
Регистрация: 20.03.2009
Сообщений: 4,654
Записей в блоге: 11
27.11.2012, 12:47 #15
Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
А если на форме 100500 элементов динамически там размещенных?
Эти 100500 элементов будут сжирать столько памяти, что на их фоне несколько сот килобайт или 1-2 мегабайта смотрятся скромно. Однако работать будет на порядок быстрее твоего перебора при помощи foreach

Добавлено через 4 минуты
Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
И работает быстрее чем сравнивать по хэш таблице строки.
Обычно map реализуется деревьями поиска. А QHash может работать еще быстрее, т.к. хеш функция от строки вычисляется один раз.
C++ (Qt)
1
uint    qHash ( const QString & key )
2
HomeR_J_SimpsoN
59 / 59 / 8
Регистрация: 15.10.2010
Сообщений: 356
27.11.2012, 12:53 #16
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
перебора при помощи foreach
Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
Лично я не вижу особого смысла в переборе каждого компонента формы.
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
на их фоне несколько сот килобайт или 1-2 мегабайта смотрятся скромно
Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
w->findChild< QPushButton * >("btn1")
На кой черт что то там дополнительно хранить, если оно и так хранится без тебя?
Лишние затраты памяти и лишний код для поиска компонента.
1
Dmitriy_M
1422 / 1303 / 130
Регистрация: 20.03.2009
Сообщений: 4,654
Записей в блоге: 11
27.11.2012, 15:20 #17
Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
На кой черт что то там дополнительно хранить, если оно и так хранится без тебя?
Лишние затраты памяти и лишний код для поиска компонента.
Поиск в мапе одна строчка, в отличие от твоих 14. И работает быстрее твоего линейного перебора.
А ты считал эту память? Какой смысл экономить несколько сот килобайтов, когда GUI будет занимать мегабайты?
1
HomeR_J_SimpsoN
59 / 59 / 8
Регистрация: 15.10.2010
Сообщений: 356
27.11.2012, 15:30 #18
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
в отличие от твоих 14
Покажи пальцем
C++ (Qt)
1
2
QWidget *w = this->findChild< QWidget * >("containerWidget");
w->findChild< QPushButton * >("btn1")->setText(tr("Нашли кнопку 1"));
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
работает быстрее твоего линейного перебора
С чего взял, что там линейный перебор? Уверен, что ты недооцениваешь Создателей кутов.

Цитата Сообщение от Dmitriy_M Посмотреть сообщение
GUI будет занимать мегабайты
Че?!

О чем спор вообще?!
Если тебе нравится использовать QMap, используй QMap. Я искренне считаю, что стандартные средства реализованы намного более адекватно и намного более знающими свое дело людьми. Посему работать они будут уж точно быстрее.

В данный момент времени я пишу интерфейс, состоящий более чем из 100 эл-тов на виджет. Таких виджетов около 10ти. Каждый формируется на лету в зависимости от условия в комбо боксе. При этом старый виджет (на место которого вставляется новый) удаляется.

А теперь подумай, как же преобразятся твои 2 строчки, когда виджет вместе с сотней наследников будет удален? Или же ты оставишь в своем QMap несуществующие виджеты?

Нравится засирать мозг себе, не засирай другим.
1
Dmitriy_M
1422 / 1303 / 130
Регистрация: 20.03.2009
Сообщений: 4,654
Записей в блоге: 11
27.11.2012, 16:32 #19
Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
С чего взял, что там линейный перебор? Уверен, что ты недооцениваешь Создателей кутов.
Вот твой код:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Попробуем сначала взять весь список сыновей для Виджета containerWidget
// Но для начала его надо тоже найти
QWidget *w = this->findChild< QWidget * >("containerWidget");
 
QObjectList l = w->children();
foreach (QObject *o, l)
{
    if (o->metaObject()->className() == "QPushButton")
    {
        QPushButton *b = static_cast< QPushButton * >(o);
        b->setText(tr("Текст изменен"));
    }
}
// Теперь просто найдем все кнопки с нашего виджета:
QList< QPushButton * > l1 = w->findChildren< QPushButton * >();
foreach (QPushButton *b, l1)
{
    if (b->objectName() == "btn1")
        b->setText(tr("Кнопка 1, текст изменен"));
    else if (b->objectName() == "btn2")
        b->setText(tr("Кнопка 2, текст изменен"));
}
 
// Теперь просто возьмем конкретную кнопку с виджета и изменим ее текст
w->findChild< QPushButton * >("btn1")->setText(tr("Нашли кнопку 1"));
w->findChild< QPushButton * >("btn2")->setText(tr("Нашли кнопку 2"));
foreach выполняется линейно, findChild работает рекурсивно и проходит по всем чилдерам.

Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
Посему работать они будут уж точно быстрее.
Рекурсивный поиск будет выполняться быстрее? Как это?
Если ты всегда пишешь такой медленный код, то естественно, что кто-то может сделать лучше.

Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
А теперь подумай, как же преобразятся твои 2 строчки, когда виджет вместе с сотней наследников будет удален? Или же ты оставишь в своем QMap несуществующие виджеты?
Никто не мешает взять и удалить/модифицировать ключи.
Но если вдруг захочется изменить где то текст, то это будет быстрее того, что ты тут написал

Не по теме:


Цитата Сообщение от HomeR_J_SimpsoN Посмотреть сообщение
Нравится засирать мозг себе, не засирай другим.
Нравиться писать говногод? Пиши, но никому не показывай.

1
HomeR_J_SimpsoN
59 / 59 / 8
Регистрация: 15.10.2010
Сообщений: 356
27.11.2012, 16:40 #20
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Вот твой код:
Если ты вчитаешься, то заметишь, что там описаны 3 способа достижения одной и той же цели.
Цитата Сообщение от Speedy Gonzales Посмотреть сообщение
а можно немного расширить ответ и небольшой пример кода дать с QList< QObject * >
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Рекурсивный поиск будет выполняться быстрее
Я ищу объект на конкретном виджете, ни один виджет которого не содержит подвиджет. Рекурсии нет.

Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Как это
На раз. Рекурсивные алгоритмы зачастую обгоняют линейные.
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Если ты всегда пишешь такой медленный код
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Нравиться писать говногод? Пиши, но никому не показывай.
Нет слов... Я в шоке =)

Цитата Сообщение от Dmitriy_M Посмотреть сообщение
Никто не мешает взять и удалить/модифицировать ключи.
Я и не спорю. Только лишь говорю, что это лишние затраты во времени, в коде и в памяти тк где то в недрах класса QObject более умный человек (на себя я не намекаю) уже это реализовал.

Спор бесполезен и безоснователен.
1
27.11.2012, 16:40
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.11.2012, 16:40

Добавление виджетов на форму [QtDesigner или вручную]
Где лучше всего делать виджеты в дизайнере или вручную.

программное добавление объектов на форму
не как не могу разобраться procedure TForm1.Button1Click(Sender: TObject);...

Программное добавление элементов в пользовательскую форму
Доброго времени суток! Есть пользовательская форма (см. вложение). Стоит...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru