I had a console-game that was written on c++ and since I am currently trying to learn Qt I decided to add GUI to this program as an exercise.
So there's main window named "gui" that inherits Qwidget. It has layout QHBoxLayout* main_h_lo. Which has 2 added layouts: 1. QStackedLayout* leftpart, 2. QGridLayout* deck. The first is some sort of menu-part. It has 4 different widgets with their layouts. For example choosing game mode or printing game score. And second layout - deck - is game table, similar to chessboard.
There's constructor code which I suppose contains the problem:
gui::gui(QWidget *parent) :
QWidget(parent), pgame(nullptr)
{
QHBoxLayout* main_h_lo = new QHBoxLayout;
main_h_lo->setMargin(0);
main_h_lo->setSpacing(0);
setLayout(main_h_lo);
//leftpart-widgets initialization:
bot_or_playerW = new QWidget;
QVBoxLayout* bot_or_playerL = new QVBoxLayout;
bot_or_playerL->addWidget(new QLabel("Choose game mode"));
QPushButton* qpb1 = new QPushButton("vs Human");
QPushButton* qpb2 = new QPushButton("vs Bot");
QObject::connect(qpb1, SIGNAL(clicked()), SLOT(pvp()));
QObject::connect(qpb2, SIGNAL(clicked()), SLOT(pvb()));
bot_or_playerL->addWidget(qpb1);
bot_or_playerL->addWidget(qpb2);
bot_or_playerW->setLayout(bot_or_playerL);
choosing_colourW = new QWidget;
QVBoxLayout* choosing_colourL = new QVBoxLayout;
choosing_colourL->addWidget(new QLabel("Choose your colour"));
QPushButton* qpb3 = new QPushButton("white(2nd turn)");
QPushButton* qpb4 = new QPushButton("black(1st turn)");
QObject::connect(qpb3, SIGNAL(clicked()), SLOT(chwh()));
QObject::connect(qpb4, SIGNAL(clicked()), SLOT(chbl()));
choosing_colourL->addWidget(qpb3);
choosing_colourL->addWidget(qpb4);
choosing_colourW->setLayout(bot_or_playerL);
score_lturnW = new QWidget;
QVBoxLayout* score_lturnL = new QVBoxLayout;
lturn = new QLabel;
pturn = new QLabel;
score = new QLabel;
score_lturnL->addWidget(lturn);
score_lturnL->addWidget(pturn);
score_lturnL->addWidget(score);
score_lturnW->setLayout(score_lturnL);
after_gameW = new QWidget;
QVBoxLayout* after_gameL = new QVBoxLayout;
winner = new QLabel;
offer_to_play_again = new QLabel("Wanna play again?");
QPushButton* qpb5 = new QPushButton("yes");
QObject::connect(qpb5, SIGNAL(clicked()), SLOT(restart()));
QPushButton* qpb6 = new QPushButton("no");
QObject::connect(qpb6, SIGNAL(clicked()), qApp, SLOT(quit()));
after_gameW->setLayout(after_gameL);
leftpart = new QStackedLayout;
leftpart->addWidget(bot_or_playerW);
leftpart->addWidget(choosing_colourW);
leftpart->addWidget(score_lturnW);
leftpart->addWidget(after_gameW);
//"rightpart" init:
deck = new QGridLayout;
deck->setMargin(0);
deck->setSpacing(0);
e_pic = QPixmap("empty.png");
b_pic = QPixmap("black.png");
w_pic = QPixmap("white.png");
pic_sz = e_pic.size();
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
{
QPushButton* tqpb = new QPushButton;
tqpb->setIcon(e_pic);
tqpb->setIconSize(pic_sz);
std::stringstream ss;
std::string s;
ss << i << j;
ss >> s;
tqpb->setObjectName(s.c_str());
deck->addWidget(tqpb, i, j);
connect(tqpb, SIGNAL(clicked()), SLOT(turn_try()));
}
main_h_lo->addLayout(leftpart);
main_h_lo->addLayout(deck);
leftpart->setCurrentWidget(bot_or_playerW);
}
I get no error or warning. The deck part is scary and ugly but it is as expected :D. The "menu" part does not show up - that is the problem. Screen: http://i.imgur.com/Sh9PU9N.jpg .
Some comments about you code -
A layout can be given the parent on construction and it will automatically become the default layout. This saves you one command, but makes it more implicit. It all depends on what you prefer - implicit or explicit.
Loose the QObject::connect. A simple 'connect' will do.
Are you sure "black(1st turn)" is correct? In a conventional chess game, white generally goes first.
You can avoid std::stringstream and use QString::number instead.
The problem has already been mentioned by 'hyde'.
Related
I want to make a QLable and a QComboBox display in one line (horizontal, let's name it as h_combination_1), and there are some similar layouts like this (e.g. h_combination_2, h_combination_3, and etc). Then I want to manage this combinations (h_combination_1..3) display vertially. But at last these combinations display horizontally, how strange it is! Could someone help me with this?
Here is the code:
void ThemeWidget::initLayout()
{
[..]
QHBoxLayout* themeLayout = new QHBoxLayout;
QLabel* themeLabel = new QLabel("Theme");
themeLayout->addWidget(themeLabel);
themeLayout->addWidget(cbox_theme);
QHBoxLayout* legendLayout = new QHBoxLayout;
QLabel* legendLabel = new QLabel("Legend");
themeLayout->addWidget(legendLabel);
themeLayout->addWidget(cbox_legend);
QHBoxLayout* animationLayout = new QHBoxLayout;
QLabel* animationLabel = new QLabel("Animation");
themeLayout->addWidget(animationLabel);
themeLayout->addWidget(cbox_animation);
antialiasCheckBox = new QCheckBox("Antialiasing");
[..]
QVBoxLayout* parametersLayout = new QVBoxLayout;
parametersLayout->addLayout(themeLayout);
parametersLayout->addLayout(legendLayout);
parametersLayout->addLayout(animationLayout);
parametersLayout->addWidget(antialiasCheckBox);
QWidget* paramsBox = new QWidget();
paramsBox->setLayout(parametersLayout);
gridLayout = new QGridLayout;
QHBoxLayout* layout = new QHBoxLayout;
layout->addLayout(gridLayout);
layout->addWidget(paramsBox);
this->setLayout(layout);
}
Here is a screenshot:
In the begining, I've just add the layout parametersLayout to layout, without binding it to a QWidget.
For example:
void ThemeWidget::initLayout()
{
[..]
QVBoxLayout* parametersLayout = new QVBoxLayout;
parametersLayout->addLayout(themeLayout);
parametersLayout->addLayout(legendLayout);
parametersLayout->addLayout(animationLayout);
parametersLayout->addWidget(antialiasCheckBox);
gridLayout = new QGridLayout;
QHBoxLayout* layout = new QHBoxLayout;
layout->addLayout(gridLayout);
layout->addWidget(parametersLayout);
this->setLayout(layout);
}
But it turned out just as same as binding parametersLayout to a QWidget.
The layoutItems in parametersLayout should be vertical, but there were not!
So I changed into the method I discribed in the details above, and the results was still the same.
I want to do serial communication in the QT inside, according to the number of serial ports to dynamically generate label, LineEdit, Button, and these three buttons can pull down the scroll bar when the size of the interface, how to do well, I write this below is dead of.
The effect of encapsulation into a method
The interface was washed last
Define QGridLayout insude QScrollArea. And add your new widgets into
that layout in code. QGridLayout::addWidget
Define table where you will show several widgets in table cells. That real complicated way.
void BaseUi::BaseScrollArea()
{
QScrollArea *pArea = new QScrollArea();
QWidget *pWidget = new QWidget();
pWidget->setStyleSheet("QWidget" "{background:white;}");
m_vbox_layout = new QVBoxLayout();
m_vbox_layout->addSpacerItem(new QSpacerItem(100, 30,
QSizePolicy::Expanding, QSizePolicy::Expanding));
pWidget->setLayout(m_vbox_layout);
pArea->setWidget(pWidget);
pArea->setWidgetResizable(true);
m_main_layout = new QVBoxLayout();
m_main_layout->addWidget(pArea);
}
void BaseUi::addAutoRecordUi(QString lab_neme, QString ledit_name)
{
QWidget *page = new QWidget;
QGridLayout *layout = new QGridLayout(page);
QLabel *label = new QLabel;
label->setText(lab_neme);
label->setFont(font());
QLineEdit *ledit = new QLineEdit;
ledit->setText(ledit_name);
ledit->setFont(font());
layout->addWidget(label, 0, 1);
layout->addWidget(ledit, 0, 2);
page->setLayout(layout);
m_vbox_layout->insertWidget(m_vbox_layout->count()-1, page);
}
void BaseUi::addMulRecordUi(QString lab_neme, QString ledit_name, QString
but_name)
{
QWidget *page = new QWidget;
QGridLayout *layout = new QGridLayout(page);
QLabel *label = new QLabel;
label->setText(lab_neme);
label->setFont(font());
QLineEdit *ledit = new QLineEdit;
ledit->setText(ledit_name);
ledit->setFont(font());
QPushButton *but = new QPushButton(but_name);
but->setFont(font());
layout->addWidget(label, 0, 1);
layout->addWidget(ledit, 0, 2);
layout->addWidget(but, 0, 3);
page->setLayout(layout);
m_vbox_layout->insertWidget(m_vbox_layout->count()-1, page);
}
Can I add some widgets like QLabel and QPushButton into a QTabWidget?
Actually, I want to do something like this:
I'm using C++ and Qt.
Thanks
It's possible, just use QTabWidget::setCornerWidget.
Quick example:
QWidget* pTabCornerWidget = new QWidget(this);
QLabel* pLabelTime = new QLabel(pTabCornerWidget);
pLabelTime->setText("10:22:20");
QPushButton* pButton = new QPushButton(pTabCornerWidget);
pButton->setText("?");
pButton->setMaximumSize(QSize(25, 25));
QHBoxLayout* pHLayout = new QHBoxLayout(pTabCornerWidget);
pHLayout->addWidget(pLabelTime);
pHLayout->addWidget(pButton);
mUI.tabWidget->setCornerWidget(pTabCornerWidget, Qt::TopRightCorner);
If you want do this stuff, I recommend you use QTabBar instead of QTabWidget. For example, your code can be (remember, that it's just a very simple example):
// Here some first widget
QWidget *wid1 = new QWidget(this);
QHBoxLayout *wid1Lay = new QHBoxLayout(wid1);
wid1Lay->addWidget(new QLabel(tr("Widget1")));
// Here some second widget
QWidget *wid2 = new QWidget(this);
QHBoxLayout *wid2Lay = new QHBoxLayout(wid2);
wid2Lay->addWidget(new QLabel(tr("Widget2")));
// Here some third widget
QWidget *wid3 = new QWidget(this);
QHBoxLayout *wid3Lay = new QHBoxLayout(wid3);
wid3Lay->addWidget(new QLabel(tr("Widget3")));
// Here your Tab bar with only bars
QTabBar *bar = new QTabBar(this);
bar->addTab("One");
bar->addTab("Two");
bar->addTab("Three");
// Here some label (for example, current time) and button
QLabel *lab = new QLabel(tr("Some text"), this);
QPushButton *but = new QPushButton(tr("Push"), this);
// Main layouts
QVBoxLayout *vLay = new QVBoxLayout(ui->centralWidget);
QHBoxLayout *hLay = new QHBoxLayout();
vLay->addLayout(hLay);
hLay->addWidget(bar);
// Spacer for expanding left and right sides
hLay->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
hLay->addWidget(lab);
hLay->addWidget(but);
vLay->addWidget(wid1);
vLay->addWidget(wid2);
vLay->addWidget(wid3);
// Some simple connect with lambda for navigation
connect(bar, &QTabBar::currentChanged, [=] (int index) {
wid1->setVisible(false);
wid2->setVisible(false);
wid3->setVisible(false);
switch(index) {
case 0: wid1->setVisible(true);
break;
case 1: wid2->setVisible(true);
break;
case 2: wid3->setVisible(true);
break;
default:{}
}
});
emit bar->currentChanged(0);
i'm working to creat an interface that dynamically generates QgroupeBox with layouts, i get the number of groupebox needed and it perfectly work. now i want to use a button to destroy these groupBoxes for a repeat section of the same action (get the number of groupeBox needed and creat them)
this is the code i used for this:
void interface::on_pushButton_12_clicked(){
int i,k;
ui->pushButton_13->setEnabled(true);
QGroupBox *first = new QGroupBox(this);
QVBoxLayout *test = new QVBoxLayout;
k = recupEdit();
ui->pushButton_12->hide();
ui->lineEdit->hide();
ui->label->hide();
for(i = 1; i<=k;i++)
{
first = creatgroupebox();
test->addWidget(first);
test->addStretch(1);
ui->tab->setLayout(test);
}
}
int interface::recupEdit(){
int k;
QString recup = ui->lineEdit->text();
k = recup.toInt(0,10);
return k;
}
QGroupBox *interface::creatgroupebox()
{
QGroupBox *group = new QGroupBox(this);
QLineEdit *Id = new QLineEdit("Id");
QLineEdit *Data1 = new QLineEdit("Data 1");
QLineEdit *Data2 = new QLineEdit("Data 2");
QLineEdit *Data3 = new QLineEdit("Data 3");
QLineEdit *Data4 = new QLineEdit("Data 4");
QLineEdit *Data5 = new QLineEdit("Data 5");
QLineEdit *Data6 = new QLineEdit("Data 6");
QLineEdit *Data7 = new QLineEdit("Data 7");
QLineEdit *Data8 = new QLineEdit("Data 8");
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(Id);
layout->addWidget(Data1);
layout->addWidget(Data2);
layout->addWidget(Data3);
layout->addWidget(Data4);
layout->addWidget(Data5);
layout->addWidget(Data6);
layout->addWidget(Data7);
layout->addWidget(Data8);
group->setLayout(layout);
return group;
}
void interface::on_pushButton_13_clicked()
{
ui->pushButton_12->show();
ui->lineEdit->show();
ui->label->show();
}
You can get all child objects by using QObject::children()
auto gb = new QGroupBox();
gb->setLayout(new QHBoxLayout());
gb->layout()->addWidget(new QLineEdit());
foreach (QObject *o, gb->layout()->children()) {
auto le = qobject_cast<QLineEdit*>(o);
if (!le)
continue;
//do what you need with your linedit
}
Is it what you want?
My C++ code(use opencv and qt):
face_detect::face_detect(QWidget *parent)
: QWidget(parent)
{
imgwidget = new showwidget("D:\\sample.avi");
imgwidget->resize(QSize(640,480));
setWindowTitle(tr("Face Detection!"));
FaceNumLabel = new QLabel(tr("face_num: "));
num = new QLabel;
num->setFrameStyle(QFrame::Panel | QFrame::Sunken);
ImgSource = new QLabel(tr("image source: "));
VedioBtn = new QPushButton(tr("from vedio"));
LocalImgBtn = new QPushButton(tr("local image"));
LeftLayout = new QVBoxLayout();
LeftLayout->addWidget(imgwidget);
LeftLayout->addWidget(FaceNumLabel);
LeftLayout->addWidget(num);
//LeftLayout->addWidget(ShowImageLabel, 3, 0, 1, 2);
RightLayout = new QVBoxLayout();
RightLayout->addWidget(ImgSource);
RightLayout->addWidget(VedioBtn);
RightLayout->addWidget(LocalImgBtn);
RightLayout->addWidget(ImgSource);
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->addLayout(LeftLayout);
mainLayout->addLayout(RightLayout);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
connect(VedioBtn, SIGNAL(clicked()), this, SLOT(openvedio()));
connect(LocalImgBtn, SIGNAL(clicked()), this, SLOT(localimg()));
}
I call widget.resize() to resize the widget, and then add it to the layout. But when I run the program, the showimgwidget's is not 640*480. Why is that?