К примеру по нажатии кнопки рядом появляется еще одна кнопка.
Как это реализовать, так как надо каждый раз давать имя новому элементу(кнопке).
pushButton_1->...
pushButton_2->...
pushButton_3->...
...
pushButton_n->...
PS желательно чтоб действие по нажатии главной кнопки передавалось и остальным (если нажму 50-ю кнопку тоже появится еще одна)RazrFalcon, в этой ситуации я всем рекомендую смотреть пример "Calculator" (examples\widgets\calculator)
for (int i = 0; i < NumDigitButtons; ++i) {
digitButtons[i] = createButton(QString::number(i), SLOT(digitClicked()));
}
тепло, теперь разберись, как определяется, какую кнопку нажали.
Пришол из этой темы
Вот собственно код, что здесь не так?.
Жалуется, что конструктор у QPushButton private
main.cpp
Всё вопрос снят, разобрался..
Чуть позже выложу рабочий пример.. авось кому пригодится..
Будь они не ладны эти указатели..
haiflive, в Qt у всех наследников QObject конструктор копирования и оператор присваивания находятся в закрытой (private) области. Т.к. операции копирования таких объектов не тривиальные. Поэтому всюду в программах Qt используется динамическое создание объектов-наследников QObject. Ну и соответственно работать с такими объектами нужно через указатель.
Как-то в голове не укладывается, что вопрос решился обёрткой на базовый QT класс..
Тоесть, всё что нужно было, это создать новый класс отнаследованый от требуемого объекта(в данном случае QPushButton), и конструктор нового класса объявить как public?.
И всё работает.. или всётаки могут быть какие-то проблемы?.
#ifndef BUTTON_H
#define BUTTON_H
#include <QToolButton>
class Button : public QPushButton
{
Q_OBJECT
public:
Button(const QString &text, QWidget *parent = 0);
QSize sizeHint() const;
};
#endif
ИМХО, лучше так
#pragma once
#include <QToolButton>
class Button
{
QPushButton* m_pButton;
public:
Button(/*...параметры...*/)
{
m_pButton=new QPushButton(/*...параметры...*/);
}
~Button()
{
if(m_pButton)delete m_pButton;
}
operator QPushButton()
{
return *m_pButton;
}
Button(const QString &text, QWidget *parent = 0);
QSize sizeHint() const;
QPushButton& GetQPushButton()
{
return *m_pButton;
}
};
Как-то всё очень сложно, пример "Калькулятор" явно не был изучен
А деструктор зачем?. Разве MOC не берёт на себя удаление объектов?. может всётаки лучше Q_OBJECT
И интересно посмотреть, как с этим классом работать..
Button BUT;
BUT.GetQPushButton().member;
Ну вот, значит в классе дописать слот и связать в конструкторе с данным сигналом QPushButton. А в слоте просто обнулить указатель-мембер
Ого как тема разрасталась пока я забросил эту затею, ну вот все таки доделал то что требовалось. Выложил упрощенный вариант проги своей.
Был использован пример Calculator и переписана функция создания кнопок, может кому пригодится.
PS: правда так и не смог избавится от формы, выдавалась "Ошибка вида: QWidget: Must construct a QApplication before a QPaintDevice" (название темы на форуме встречал такое же). Буду благодарен за способ ухода от форм. Так как особо навороченным интерфейсом не интересуюсь.
PSS: ну а если надо совсем просто то можно и так:
//создаем 10 бесполезных кнопок
for (int i=0; i<10; i++)
{
QPushButton* button = new QPushButton();
tableWidget->setCellWidget(i,0,button);
}
Правда кнопки не несут никакого действия, зато пригодилось мне для создания "неограниченного количества" QgraphicsView, очень удобно.Ну вот наконец-то я осилил пример с кнопкой..
Создаётся кнопка при нажатии на которую создаётся аналогичная(++N), и так до бесконечности..
и представляю код на ваш суд..
button.h
#ifndef BUTTON_H
#define BUTTON_H
#include <QToolButton>
class Button : public QToolButton
{
Q_OBJECT
public:
Button(const QString &text, QWidget *parent = 0);
QSize sizeHint() const;
};
#endif
#include <QtGui>
#include "button.h"
Button::Button(const QString &text, QWidget *parent)
: QToolButton(parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
setText(text);
}
QSize Button::sizeHint() const
{
QSize size = QToolButton::sizeHint();
size.rheight() += 20;
size.rwidth() = qMax(size.width(), size.height());
return size;
}
#ifndef TEXT_BUTTON_H
#define TEXT_BUTTON_H
#include <iostream>
#include <QObject>
#include <QtGui>
/*
* можно не использовать класс "button.h" и писать вместо
* Button *button = new Button("new"+QString::number(Schet));
* QToolButton *button = new QToolButton("new"+QString::number(Schet));
* но так удобнее
*/
#include "button.h"
class text_button : public QObject
{
Q_OBJECT
/* Здесь будут храниться все указатели на кнопки */
QMap<int,Button*> mapNewButtons;
int Schet; /* счётчик кнопок */
public:
explicit text_button(QObject *parent = 0);
Button *NewButton();
void MAddButton();
signals:
public slots:
void clickMainBtn();
};
#endif // TEXT_BUTTON_H
#include "text_button.h"
text_button::text_button(QObject *parent) :
QObject(parent), Schet(0)
{
}
Button *text_button::NewButton()
{
Button *button = new Button("new"+QString::number(Schet));
/* Можно обработать кнопку сразу при создании */
/*
QObject::connect(button, SIGNAL(clicked()),
this, SLOT(clickMainBtn())
);
*/
qDebug() << SLOT(clickMainBtn());
return button;
}
void text_button::MAddButton()
{
/* Конечно можно было всё это сделать внутри функции NewButton(),
* но цель была показать как работать между классами
* имеено поэтому понадобился контейнерс с указателями */
mapNewButtons[++Schet] = NewButton();
mapNewButtons[Schet]->show();
/* Прикручиваем сигнал "создать новую кнопку"
* к только что созданной кнопке */
QObject::connect(mapNewButtons[Schet], SIGNAL(clicked()),
this, SLOT(clickMainBtn())
);
}
void text_button::clickMainBtn()
{
emit MAddButton();
}
#include "text_button.h"
int main(int argc, char **argv)
{
QApplication app(argc,argv);
QWidget wgt;
/* Первая кнопка */
QPushButton mainbtn("Add new Button");
QVBoxLayout vbl;
text_button buttonNew; /* Класс дл создания N кнопок */
vbl.addWidget(&mainbtn);
wgt.setLayout(&vbl);
/* Здесь мы просто создаём новую кнопку используя наш класс */
Button *btn = buttonNew.NewButton();
/* аналогично можно работать с новой кнопкой */
vbl.addWidget(btn);
wgt.show();
/* Создаём для певой главной кнопки сигнал
* "создать новую кнопку" используя наш класс */
QObject::connect(&mainbtn, SIGNAL(clicked()),
&buttonNew, SLOT(clickMainBtn())
);
return app.exec();
}
тему разделил: http://www.forum.crossplatform.ru/index.php?showtopic=5288
Опять не известно количество элементов.
1) Человек вводит число и создается такое же количество qgraphicsview, как потом к ним обращаться.
2) -//- checkbox
С кнопками и примером калькулятора уже не получится так как там используется QToolButton
Идей пока не каких.
Litkevich Yuriy, что то типа множества слоев, ака gif анимация покадрово.
Нужно для начала сделать чтоб был аналог flowlayout, только пример мне как то не очень понравился, другим способом хочу.
а для checkbox, грузится список из файла, и человек выбирает нужные пункты. Заранее не известно понятное дело сколько их.
Как создать и обратится к элементу, любому, если я не знаю будет он создан или нет.
Типа qgraphicsview_1, qgraphicsview_2, qgraphicsview_3 ... а потом к нужному обращаться, но не знаю сначала скока х будет то!
RazrFalcon, ты опять про внутренности.
Как человек работает с твоей программой? что он делает?
Бээ... пользователь ввел число 10. Появилось 10 qgraphicsview. Потом он нажал на один правой кнопкой мыши и выбрал добавить изобраение, и оно должно загрузится именно в этот qgraphicsview. Потом нажал закрыть/удалить и он удалился. Потом поменять и 4-й стал 6-м. Потом растянул окно и они и 2х5 штук стали 3х3 и еще 1-н в низу короче. То есть аналог flowlayout из кьюшных примеров. Потом говорит сохранить некоторые к примеру. Появляется список с checkbox и он ставит галочки напротив нужных кадров и сохраняет.
Вот, чисто со стороны пользователя.
PS qgraphicsview двигаю через ResizeEvent+setGeometry
PSS такое чуство что я не вижу что то явное и обыкновенное.
BRE, спасибо, то что нужно, как оказалось.
QList<QWidget *> list;
list.append(graphicsView);
list[0]->setGeometry(0,0,50,50);
Ну и производные отсюдова вещи.QGraphicsView* graphicsViev = new QGraphicsView();
то ничего не выходит, пустое окно. QGraphicsView* graphicsViev[i] = new QGraphicsView();
QList<QGraphicsView *> list;
for(int i=0;i<N;i++)
{
list.append(new QGraphicsView(this));
}
Алексей1153, что значит показать, у меня обычно они так видны (все что я таким способом создавал), а при setVisible/show просто отдельный виджет появляется с graphicsViev. Циклом твои тоже ничего не видно, хотя компилит. Спасибо за цикл кстати.
Litkevich Yuriy, ну их создается ровно столько сколько нужно, циклом, так что лишних нет.
я же писал, что то типа раскадровки гиф/видео, там же их будет 1000-чи...
RazrFalcon, ну, предположим, он видим. Но ты указатель на родительский виджет не передаёшь
Алексей1153, спасибо за идею попробую ограничится только влезшими на экран.
Спасибо всем, все работает.
Создаем:
QList<QGraphicsView *> list;
for(int i=0;i<10;i++)
{
list.append(new QGraphicsView(this));
}
Изменяем:int x=0, y=0;
for (int i=0; i<list.count();i++)
{
list[i]->setGeometry(x,y,50,50);
x+=51;
y+=51;
}
RazrFalcon, ещё два момента:
1) поскольку QList<QGraphicsView *> list предположительно - член класса, то перед циклом заполнения не забывай проверить, сколько элементов уже есть в списке. Не забывай также удалить через delete (как вариант, можно сделать оболочку для указателя, чтобы не приходилось вызывать delete вручную - щас приведу ниже)
//вумный указатель для хранения в векторе и иже с ним
template<typename T>
struct s_VectorPtr
{
T* m_p;
s_VectorPtr()
{
m_p=0;
}
s_VectorPtr(const s_VectorPtr& o2)
{
m_p=0;
(*this)=o2;
}
void createIfNotYet()
{
if(!m_p)
{
m_p=new T;
}
}
~s_VectorPtr()
{
if(m_p)
{
delete m_p;
m_p=0;
}
}
void operator=(const s_VectorPtr& o2)
{
if(m_p)
{
delete m_p;
m_p=0;
}
T* p=o2.m_p;
((s_VectorPtr&)o2).m_p=0;
m_p=p;
}
T* operator ->()
{
return m_p;
}
};
//обявление теперь выглядит так
QList< s_VectorPtr<QGraphicsView> > list;//тут "*" не надо!
Алексей1153, для чего столько всего в деструкторе?
~s_VectorPtr()
{
if(m_p)
{
delete m_p;
m_p=0;
}
}
~s_VectorPtr()
{
delete m_p;
}
BRE, проверка if(m_p) здесь обязательна: смотри работу operator= Стандарт стандартом, но грабли потом искать не хочется, если что
ну а обнуление висячего указателя - это просто полезная привычка
Хорошо, пусть будет так:
~s_VectorPtr()
{
#ifdef BRE
delete m_p;
#else
if(m_p)
{
delete m_p;
m_p=0;
}
#endif
}
Алексей1153, я вовсе не занудствую.
Ты предлагаешь свой код человеку, который учиться. Этот код избыточен. Для чего учить человека писать избыточный код?
У тебя это вошло в привычку, но не обязательно (и, наверное, не правильно), что бы это вошло в его привычку. Отсюда и мой комментарий.
BRE, дык, я ж ничего. У всех свой стиль, он прочитает всё, что мы тут понаписали - и выберет теперь свой стиль. Правильно рассуждаю ? ))
DEADHUNT, я вообще про C++ речь веду. А где, кстати, в Qt это есть?
А про "не совсем корректность" - так вектору не нужен конструктор копирования и прочие мелочи, там оператор присваивания только нужен. Всё остальное -
"избыточность кода" © BRE
Ненужные препирательства всё это. Я подсказал путь, а решений - туча, каждому нравится своё
а где сей стандарт глядеть?
А насчёт корректности работы - оно работает, одного только оператора присваивания достаточно. Правда, у меня в проекте std::vector используется, но работает без ошибок - очень хорошо и длительно тестировано
http://open-std.org/JTC1/SC22/WG21/docs/papers/2010/n3090.pdf
насчёт работы это как раз из-за твоего зануления указателя в деструкторе, потому-что деструктор вызывается несколько раз вместо одного, попробуй сделать так в своём классе:
class smart_ptr {
smart_ptr(const smart_ptr &);
....
};
class smart_ptr {
smart_ptr(const smart_ptr &) = delete;
....
};
DEADHUNT, не мог бы ты пояснить такую строчку:
Синтаксис я тоже не понял что означает "= delete" и "= default" после прототипа функции?
class some_class {
public:
some_class() = default;
some_class(int a) : m_a(a) { }
private:
int m_a;
};
some_class a;
some_class a(10);
понятно
то есть мне нужно добавить
s_VectorPtr(const s_VectorPtr& o2)
{
m_p=0;
(*this)=o2;
}
DEADHUNT, так так, тут вот поподробнее. Почему разрушающее? Я копирую указатель в новую оболочку, а сам "указуемый" объект жив.
Это вот в операторе = у меня заменяемый объект отправляется в кучу, а принимаемый его заменяет
Почему нельзя в контейнере использовать, ведь контейнер ничего неиспортит, вызывая конструкторы и операторы
Я главную цель всей этой эпопеи не сказал (думал, и так понятно) - безопасное использование resize() контейнера + автоудаление "указуемых" объектов в кучу
получается так:
X<T> b = ...;
X<T> a(b); // b - передаёт указатель a
std::vector<X<T>> v;
v.push_back(a); // a - разрушается
v.front(); // разрушается объект в векторе
Я не собирался отдельно объявлять переменные класса s_VectorPtr<T> , всем этим заведует сам вектор (структура s_VectorPtr, кстати, в проекте, откуда выдрано, описана как приватная внутри класса с вектором)
Теперь я понимаю твоё возмущение, а также , почему у меня всё работает, хотя, по стандарту, не должно Я реализовал и использовал частный случай
Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)