Консультация № 145972
04.10.2008, 15:16
0.00 руб.
0 2 1
Здравствуйте, уважаемые эксперты. Как описать в C++ класс графических объектов-кнопок(которых должно быть 6 на экране) при щелчке на одной из них вызывается функция с параметром разным для каждой кнопки? Ну и чтобы надписи на них были разными. Также нужен еще один большой графический элемент, на котором бы изменялся текст в ходе работы программы, размеры его должны автоматически подгоняться под размеры ее окна.Соотвественно и объем бы текста выведенного на нем должен подстраиваться под размер. Я очень просил бы написать примерный код размещающий все это хозяйство на экране, поскольку в области графики не очень силен и имел опыт работы в основном с консольными приложениях. Спасибо.

Обсуждение

давно
Старший Модератор
17042
808
05.10.2008, 10:23
общий
это ответ
Здравствуйте, Alexg!
К сожалению, в своём вопросе Вы не указали операционную систему, под которой работаете, и предпочитаемую среду разработки. Поэтому привожу решение для Linux (пример №1 в приложении), компилятор g++ 4.1, библиотека Qt 3.3.8 (впрочем, под Windows пример №1 можно откомпилировать с использованием MS Visual C++ 6 и библиотеки Qt 3.2.1) и для Windows (пример №2 в приложении), среда разработки Borland C++ Builder или Turbo C++ Explorer.
Разберём Вашу задачу на следующем примере. Предположим, что у нас есть 6 кнопок класса TButton с открытым (public) свойством уникального идентификатора - тега (Tag). При нажатии на ту или иную кнопку выводится сообщение с номером её тега. Кроме того, это сообщение дублируется на ярлыке (label), находящемся под группой кнопок, расположенных в 3 колонках в 2 ряда. Размер ярлыка автоматически подстраивается под размеры текста.
Пример 1.
Объявим класс TButton, унаследовав его от Qt-класса QPushButton. В качестве открытого свойства класса объявим строковую переменную QString sTag; Объявим также слот, который будет вызываться при щелчке на кнопке - void ClickedSlot(); Кроме того, объявим сигнал, который будет посылать тег кнопки, при щелчке на ней: void clicked(QString&);
В реализации класса установим соединение между щелчком по кнопке и вызовом слота ClickedSlot(): connect(this, SIGNAL(clicked()), this, SLOT(ClickedSlot()));
Слот будет генерировать сигнал, посылающий тег кнопки: emit clicked(sTag);
В классе центрального виджета TCentralWidget разместим виджеты кнопок (класс TButton) и ялыка для вывода текста (QLabel* pTextLabel) с помощью менеджеров компоновки (layouts), которые обеспечивают аккуратное размещение виджетов на форме приложения, а также подстраивание их размеров под размеры текста.
Логика приложения реализована в слоте ButtonClickedSlot(QString&) центрального виджета, в который в качестве параметра передаётся тег вызвавшей кнопки:
Код:

void TCentralWidget::ButtonClickedSlot(QString& sTag)
{
QString sMessage = trUtf8("Нажата кнопка номер ") + sTag;
QMessageBox::information(this, "Buttons", sMessage); // Сообщение с тегом кнопки

sMessage = "<p align=Center>" + trUtf8("Последней была нажата кнопка номер ") + sTag + "</p>";
pTextLabel->setText(sMessage); // Сообщение на ярлыке
}

Пример 2.
Установим свойство Caption сгенерированной формы приложения в "Кнопки", а Name - в MainForm. Разместим на форме 6 кнопок класса TButton в 3 колонках в 2 ряда. Поскольку в Borland C++ Builder / Turbo C++ Explorer не имеет менеджеров компоновки, то кнопки придётся выравнивать на форме по линиям сетки вручную, либо воспользовавшись командой контекстного меню Align...
Внизу разместим ярлык класса TLabel. Установим свойство Caption ярлыка в "Нажмите кнопку", AutoSize и WordWrap в true, что обеспечит подстраивание размера ярлыка под размер текста.
Класс TButton Билдера уже содержит свойство Tag, являющееся целочисленной переменной. Установим свойство Tag первой кнопки в 1, второй - в 2 и т.п.
Логику приложения реализуем в обработчике события щелчка по первой кнопке:
Код:

void __fastcall TMainForm::Button1Click(TObject *Sender)
{
TButton* pButton = (TButton*)Sender;
AnsiString sTag = IntToStr(pButton->Tag); // Преобразуем целочисленную переменную в строку
AnsiString sMessage = "Нажата кнопка номер " + sTag;
ShowMessage(sMessage); // Сообщение с тегом кнопки
sMessage = "Последней была нажата кнопка номер " + sTag;
TextLabel->Caption = sMessage; // Сообщение на ярлыке
}

В качестве аргумента обработчик события принимает компонент, вызвавший событие - щелчок по кнопке: TObject *Sender
Объявим переменную-указатель на объект класса TButton и присвоим ему адрес объекта, вызвавшего щелчок по кнопке:
TButton* pButton = (TButton*)Sender;
После чего мы можем в функции-обработчике вызывать то или иное действие в зависимости от тега кнопки.
Для того, чтобы обработчик Button1Click вызывался при щелчке по любой кнопке, установим Events для каждой из 6 кнопок по событию OnClick в Button1Click.
P.S. Также группу кнопок можно было реализовать в виде массива указателей на объекты, что разумно в случае их большого количества.

Приложение:
// Пример 1
// Файл TButton.h
//--------------------------------------------------------
#ifndef _TButton_h_
#define _TButton_h_
//--------------------------------------------------------
#include <qpushbutton.h>
//--------------------------------------------------------
class TButton : public QPushButton
{
Q_OBJECT

public:
TButton(QWidget* pParent = 0, const char* psName = 0);
~TButton();

QString sTag;

signals:
void clicked(QString&);

protected slots:
void ClickedSlot();
};
//--------------------------------------------------------
#endif
// Файл TButton.cpp
//--------------------------------------------------------
#include "TButton.h"
//--------------------------------------------------------
TButton::TButton(QWidget* pParent, const char* psName)
: QPushButton(pParent, psName)
{
sTag = "0";

connect(this, SIGNAL(clicked()), this, SLOT(ClickedSlot()));
}
//--------------------------------------------------------
TButton::~TButton()
{
}
//--------------------------------------------------------
void TButton::ClickedSlot()
{
emit clicked(sTag);
}
//--------------------------------------------------------
// Файл TCentralWidget.h
//--------------------------------------------------------
#ifndef _TCentralWidget_h_
#define _TCentralWidget_h_
//--------------------------------------------------------
#include <qwidget.h>
//--------------------------------------------------------
class QVBoxLayout;
class QGridLayout;
class TButton;
class QHBoxLayout;
class QLabel;
//--------------------------------------------------------
class TCentralWidget : public QWidget
{
Q_OBJECT

public:
TCentralWidget(QWidget* pParent = 0, const char* psName = 0, WFlags Flag = 0);
~TCentralWidget();

private:
QVBoxLayout* pMainLayout;
QGridLayout* pButtonsLayout;
QHBoxLayout* pTextLayout;

TButton* pButton1;
TButton* pButton2;
TButton* pButton3;
TButton* pButton4;
TButton* pButton5;
TButton* pButton6;

QLabel* pTextLabel;

protected slots:
void ButtonClickedSlot(QString&);
};
//--------------------------------------------------------
#endif
// Файл TCentralWidget.cpp
//--------------------------------------------------------
#include "TCentralWidget.h"
#include "TButton.h"
//--------------------------------------------------------
#include <qlayout.h>
#include <qlabel.h>
#include <qmessagebox.h>
//--------------------------------------------------------
TCentralWidget::TCentralWidget(QWidget* pParent, const char* psName, WFlags Flag)
: QWidget(pParent, psName, Flag)
{
pMainLayout = new QVBoxLayout(this, 5, 5, "MainLayout");

pButtonsLayout = new QGridLayout(pMainLayout, 2, 3, 5, "ButtonsLayout");

pButton1 = new TButton(this);
pButton1->sTag = "1";
pButton1->setText(trUtf8("Кнопка 1"));
pButtonsLayout->addWidget(pButton1, 0, 0);

pButton2 = new TButton(this);
pButton2->sTag = "2";
pButton2->setText(trUtf8("Кнопка 2"));
pButtonsLayout->addWidget(pButton2, 0, 1);

pButton3 = new TButton(this);
pButton3->sTag = "3";
pButton3->setText(trUtf8("Кнопка 3"));
pButtonsLayout->addWidget(pButton3, 0, 2);

pButton4 = new TButton(this);
pButton4->sTag = "4";
pButton4->setText(trUtf8("Кнопка 4"));
pButtonsLayout->addWidget(pButton4, 1, 0);

pButton5 = new TButton(this);
pButton5->sTag = "5";
pButton5->setText(trUtf8("Кнопка 5"));
pButtonsLayout->addWidget(pButton5, 1, 1);

pButton6 = new TButton(this);
pButton6->sTag = "6";
pButton6->setText(trUtf8("Кнопка 6"));
pButtonsLayout->addWidget(pButton6, 1, 2);

pTextLayout = new QHBoxLayout(pMainLayout, 5, "TextLayout");

pTextLabel = new QLabel(this, "TextLabel");
pTextLabel->setText(trUtf8("<p align=Center>Нажмите кнопку...</p>"));
pTextLayout->addWidget(pTextLabel);

connect(pButton1, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton2, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton3, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton4, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton5, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton6, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
}
//--------------------------------------------------------
TCentralWidget::~TCentralWidget()
{
}
//--------------------------------------------------------
void TCentralWidget::ButtonClickedSlot(QString& sTag)
{
QString sMessage = trUtf8("Нажата кнопка номер ") + sTag;
QMessageBox::information(this, "Buttons", sMessage);

sMessage = "<p align=Center>" + trUtf8("Последней была нажата кнопка номер ") + sTag + "</p>";
pTextLabel->setText(sMessage);
}
//--------------------------------------------------------
// Файл TMainForm.h
//--------------------------------------------------------
#ifndef _TMainForm_h_
#define _TMainForm_h_
//--------------------------------------------------------
#include <qmainwindow.h>
//--------------------------------------------------------
class TCentralWidget;
//--------------------------------------------------------
class TMainForm : public QMainWindow
{
Q_OBJECT

public:
TMainForm(QWidget* pParent = 0, const char* psName = "MainForm", WFlags Flag = WDestructiveClose);
~TMainForm();

private:
TCentralWidget* pCentralWidget;
};
//--------------------------------------------------------
#endif
// Файл TMainForm.cpp
//--------------------------------------------------------
#include "TMainForm.h"
#include "TCentralWidget.h"
//--------------------------------------------------------
TMainForm::TMainForm(QWidget* pParent, const char* psName, WFlags Flag)
: QMainWindow(pParent, psName, Flag)
{
pCentralWidget = new TCentralWidget(this, "CentralWidget");
setCentralWidget(pCentralWidget);

setCaption(trUtf8("Кнопки"));
}
//--------------------------------------------------------
TMainForm::~TMainForm()
{
}
//--------------------------------------------------------
// Файл main.cpp
//------------------------------------------------------------------------
#include <qapplication.h>
//------------------------------------------------------------------------
#include "TMainForm.h"
//------------------------------------------------------------------------
int main(int argc, char* argv[])
{
QApplication MyProgramme(argc, argv);
TMainForm* pMainWindow = new TMainForm;
MyProgramme.setMainWidget(pMainWindow);
pMainWindow->show();
return MyProgramme.exec();
}

// Пример 2
// Файл MainUnit.cpp
//---------------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop

#include "MainUnit.h"
//---------------------------------------------------------------------------
#pragma resource "*.dfm"
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::Button1Click(TObject *Sender)
{
TButton* pButton = (TButton*)Sender;
AnsiString sTag = IntToStr(pButton->Tag);
AnsiString sMessage = "Нажата кнопка номер " + sTag;
ShowMessage(sMessage);
sMessage = "Последней была нажата кнопка номер " + sTag;
TextLabel->Caption = sMessage;
}
//---------------------------------------------------------------------------
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
давно
Старший Модератор
17042
808
06.10.2008, 06:43
общий
Цитата: 230845

Понимаете, должно происходить обращение к одной функции с параметром идентифицирующим нажатую клавишу .Эта функция мной уже написана ( она производит некоторые операции по чтению из файлов). Вся загвоздка для меня заключалась как ее соединить с визуальным интерфейсом. Теперь с этим все вроде решено, я включил ее в описание TCentralWidget, но еще надо продублировать эти вызовы с клавиатуры. Желательно, конечно, чтобы клавиши были Home, End, PageUp, PageDown, стрелка вверх, стрелка вниз. И, собственно, те же 6 вариантов параметра в функцию.

Необходимо переопределить событие нажатия на клавишу.
Добавьте в заголовочный файл класса TCentralWidget строчки:
Код:

protected:
void keyPressEvent(QKeyEvent* pKeyEvent);

Реализация функции:
Код:

void TCentralWidget::keyPressEvent(QKeyEvent* pKeyEvent)
{
switch(pKeyEvent->key())
{
case Qt::Key_Home:
{
QMessageBox::information(0, "Buttons", QObject::trUtf8("Нажата клавиша "Home""));
break;
}
case Qt::Key_End:
{
QMessageBox::information(0, "Buttons", QObject::trUtf8("Нажата клавиша "End""));
break;
}
case Qt::Key_Prior:
{
QMessageBox::information(0, "Buttons", QObject::trUtf8("Нажата клавиша "Страница вверх""));
break;
}
case Qt::Key_Next:
{
QMessageBox::information(0, "Buttons", QObject::trUtf8("Нажата клавиша "Страница вниз""));
break;
}
default:
{
QMessageBox::warning(0, "Buttons", QObject::trUtf8("Неизвестная клавиша!"));
}
}
pKeyEvent->accept();
}

Тем самым, полностью исходный тест виджета будет выглядеть так:
Код:

// Файл TCentralWidget.h
//--------------------------------------------------------
#ifndef _TCentralWidget_h_
#define _TCentralWidget_h_
//--------------------------------------------------------
#include <qwidget.h>
//--------------------------------------------------------
class QVBoxLayout;
class QGridLayout;
class TButton;
class QHBoxLayout;
class QLabel;
class QKeyEvent;
//--------------------------------------------------------
class TCentralWidget : public QWidget
{
Q_OBJECT

public:
TCentralWidget(QWidget* pParent = 0, const char* psName = 0, WFlags Flag = 0);
~TCentralWidget();

private:
QVBoxLayout* pMainLayout;
QGridLayout* pButtonsLayout;
QHBoxLayout* pTextLayout;

TButton* pButton1;
TButton* pButton2;
TButton* pButton3;
TButton* pButton4;
TButton* pButton5;
TButton* pButton6;

QLabel* pTextLabel;

protected:
void keyPressEvent(QKeyEvent* pKeyEvent);

protected slots:
void ButtonClickedSlot(QString&);
};
//--------------------------------------------------------
#endif

// Файл TCentralWidget.cpp
//--------------------------------------------------------
#include "TCentralWidget.h"
#include "TButton.h"
//--------------------------------------------------------
#include <qlayout.h>
#include <qlabel.h>
#include <qmessagebox.h>
#include <qevent.h>
//--------------------------------------------------------
TCentralWidget::TCentralWidget(QWidget* pParent, const char* psName, WFlags Flag)
: QWidget(pParent, psName, Flag)
{
pMainLayout = new QVBoxLayout(this, 5, 5, "MainLayout");

pButtonsLayout = new QGridLayout(pMainLayout, 2, 3, 5, "ButtonsLayout");

pButton1 = new TButton(this);
pButton1->sTag = "1";
pButton1->setText(trUtf8("Кнопка 1"));
pButtonsLayout->addWidget(pButton1, 0, 0);

pButton2 = new TButton(this);
pButton2->sTag = "2";
pButton2->setText(trUtf8("Кнопка 2"));
pButtonsLayout->addWidget(pButton2, 0, 1);

pButton3 = new TButton(this);
pButton3->sTag = "3";
pButton3->setText(trUtf8("Кнопка 3"));
pButtonsLayout->addWidget(pButton3, 0, 2);

pButton4 = new TButton(this);
pButton4->sTag = "4";
pButton4->setText(trUtf8("Кнопка 4"));
pButtonsLayout->addWidget(pButton4, 1, 0);

pButton5 = new TButton(this);
pButton5->sTag = "5";
pButton5->setText(trUtf8("Кнопка 5"));
pButtonsLayout->addWidget(pButton5, 1, 1);

pButton6 = new TButton(this);
pButton6->sTag = "6";
pButton6->setText(trUtf8("Кнопка 6"));
pButtonsLayout->addWidget(pButton6, 1, 2);

pTextLayout = new QHBoxLayout(pMainLayout, 5, "TextLayout");

pTextLabel = new QLabel(this, "TextLabel");
pTextLabel->setText(trUtf8("<p align=Center>Нажмите кнопку...</p>"));
pTextLayout->addWidget(pTextLabel);

connect(pButton1, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton2, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton3, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton4, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton5, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
connect(pButton6, SIGNAL(clicked(QString&)), this, SLOT(ButtonClickedSlot(QString&)));
}
//--------------------------------------------------------
TCentralWidget::~TCentralWidget()
{
}
//--------------------------------------------------------
void TCentralWidget::ButtonClickedSlot(QString& sTag)
{
QString sMessage = trUtf8("Нажата кнопка номер ") + sTag;
QMessageBox::information(this, "Buttons", sMessage);

sMessage = "<p align=Center>" + trUtf8("Последней была нажата кнопка номер ") + sTag + "</p>";
pTextLabel->setText(sMessage);
}
//--------------------------------------------------------
void TCentralWidget::keyPressEvent(QKeyEvent* pKeyEvent)
{
switch(pKeyEvent->key())
{
case Qt::Key_Home:
{
QMessageBox::information(0, "Buttons", QObject::trUtf8("Нажата клавиша "Home""));
break;
}
case Qt::Key_End:
{
QMessageBox::information(0, "Buttons", QObject::trUtf8("Нажата клавиша "End""));
break;
}
case Qt::Key_Prior:
{
QMessageBox::information(0, "Buttons", QObject::trUtf8("Нажата клавиша "Страница вверх""));
break;
}
case Qt::Key_Next:
{
QMessageBox::information(0, "Buttons", QObject::trUtf8("Нажата клавиша "Страница вниз""));
break;
}
default:
{
QMessageBox::warning(0, "Buttons", QObject::trUtf8("Неизвестная клавиша!"));
}
}
pKeyEvent->accept();
}
//--------------------------------------------------------
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
Форма ответа