Russian Qt Forum
Апрель 19, 2024, 11:56 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QHBoxLayout . В чем проблема ?  (Прочитано 6013 раз)
dss
Гость
« : Декабрь 24, 2018, 15:41 »

Добрый день.
Помогите с  проблемой :
-------------------------------------------------------------------------------------------------------------------------------
main.cpp
#pragma once
#include "test1.h"
 #include <QtWidgets/QApplication>
                         

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

   QApplication a(argc, argv);
   test1 *w = new test1;

   w->setGeometry(400, 100, 700, 500);

   init_test();

   w->show();

   return a.exec();
}
-------------------------------------------------------------------------------------------------------------------------------
test1.h
#pragma once

#include <QtWidgets/QMainWindow>
#include <qdialog>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>

void init_test();

class test1 : public QDialog
{
   Q_OBJECT
public:
   test1(QWidget *parent = Q_NULLPTR);

   QLabel *firstLineLabel[11]; // место под картинки первого ряда
   QHBoxLayout *firstLinelayout;

   QLabel *secondLineLabel[11]; // место под картинки 2 ряда
   QHBoxLayout *secondLinelayout ;

   QLabel *firstCount;
   QLabel *secondCount;


   QPushButton *push1;      // кнопки
   QPushButton *push2;
   QPushButton *push3;
   QPushButton *push4;
   QPushButton *push5;

   QVBoxLayout *mainlayout;

   void  Show_(QString deck[],int a, int b ) // формируем 1й лєйаут и 2й 
   {

      while ((firstLinelayout->takeAt(0)) != 0)
      {
         // удаляет все єлементі из лайаута
      }
      firstLinelayout->addStretch(1);

      for (int i = 0; i < a; i++)
      {
         firstLineLabel->setPixmap(QPixmap(deck));
         firstLinelayout->addWidget(firstLineLabel);
      };

      firstLinelayout->addStretch(1);
      firstCount->setText(QString::number(a));
      firstLinelayout->addWidget(firstCount);


      while ((secondLinelayout->takeAt(0)) != 0)
      {
         // удаляет все єлементі из лайаута
      }
      secondLinelayout->addStretch(1);
      for (int i = 0; i < b; i++)
      {
         secondLineLabel->setPixmap(QPixmap(deck[i+ 26]));
         secondLinelayout->addWidget(secondLineLabel);
      };

      secondLinelayout->addStretch(1);
      secondCount->setText(QString::number(b));
      secondLinelayout->addWidget(secondCount);

   }


public slots:
   void push1Slot(); 
   void push2Slot();
   void push3Slot();
   void push4Slot();
   void push5Slot();

private:

};
-------------------------------------------------------------------------------------------------------------------------------
test1.cpp
#include "test1.h"
#include <QString>
 
using namespace std;
int count1Line = 0;
int count2Line = 0;
QString  deck[52];

test1::test1(QWidget *parent)
   : QDialog(parent)
{
   for (int i = 0; i < 10; i++)
      firstLineLabel = new QLabel();

   firstLinelayout = new QHBoxLayout;

   for (int i = 0; i < 10; i++)
      secondLineLabel = new QLabel();

   secondLinelayout = new QHBoxLayout;

    firstCount = new QLabel();
    secondCount = new QLabel();

   push1 = new QPushButton(" +1 pic 1st Line ");
   push2 = new QPushButton(" clear 1st Line ");
   push3 = new QPushButton(" +1 pic 2st Line ");
   push4 = new QPushButton(" clear 2st Line ");
   push5 = new QPushButton("  Random  ");

   QHBoxLayout *pushlayout = new QHBoxLayout;
   pushlayout->addWidget(push1);
   pushlayout->addWidget(push2);
   pushlayout->addWidget(push3);
   pushlayout->addWidget(push4);
   pushlayout->addWidget(push5);

   mainlayout = new QVBoxLayout;
   mainlayout->addLayout(firstLinelayout);
   mainlayout->addLayout(secondLinelayout);
   mainlayout->addLayout(pushlayout);
   setLayout(mainlayout);

   connect(push1, SIGNAL(clicked()), this, SLOT(push1Slot()));
   connect(push2, SIGNAL(clicked()), this, SLOT(push2Slot()));
   connect(push3, SIGNAL(clicked()), this, SLOT(push3Slot()));
   connect(push4, SIGNAL(clicked()), this, SLOT(push4Slot()));
   connect(push5, SIGNAL(clicked()), this, SLOT(push5Slot()));

}

void test1::push1Slot() // добавляем 1 картинку в 1ю линию
{
   count1Line++;
   if (count1Line > 10) count1Line = 10;
   Show_(deck,count1Line, count2Line);
}
void test1::push2Slot() // очищаем 1ю линию
{
   count1Line=0;
   Show_(deck,count1Line, count2Line);
}
void test1::push3Slot()// добавляем 1 картинку в 2ю линию
{
   count2Line++;
   if (count2Line > 10) count2Line = 10;
   Show_(deck, count1Line, count2Line);
}
void test1::push4Slot() // очищаем 2ю линию
{
   count2Line = 0;
   Show_(deck, count1Line, count2Line);
}

void test1::push5Slot()  // рандомное колво картинок на каждой линии
{
   count1Line = rand() % 10;
   count2Line = rand() % 10;
   Show_(deck, count1Line, count2Line);
}

void init_test() // создаем ссылки на картинки
{
   setlocale(LC_ALL, "Russian");
   int Size_;
   QString Res;
   char Card_Mast[] = { 's' , 'c', 'd', 'h' };
   char Card_nominal[] = { '2','3','4','5','6','7','8','9','T','J','Q','K','A' };

   for (int i = 0; i < 4; i++)
      for (int j = 0; j < 13; j++)                    
      {
         Size_ = i * 13 + j;
         Res = ":/test1/Resources/";
         Res.append(Card_nominal[j]);
         Res.append(Card_Mast);
         Res.append(".png");

          deck[Size_] =   Res;
      }

}
-------------------------------------------------------------------------------------------------------------------------------

программа по нажатию кнопки должна выводить на экран определенное количество картинок и  цифру ( кол-во картинок в ряду).
В первый раз все нормально :
 test2.png

то при следующем нажатии кнопки "рандом" видно что второй ряд отображается "с мусором"
 test2.png

В чем проблема ?

Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #1 : Декабрь 24, 2018, 21:48 »

А этот код компилируется?
Смущает
Код
C++ (Qt)
firstLineLabel = new QLabel();
Записан
dss
Гость
« Ответ #2 : Декабрь 24, 2018, 23:32 »

А этот код компилируется?
Смущает
Код
C++ (Qt)
firstLineLabel = new QLabel();


ну если я прикрепил скриншоты работающей программы, то вроде компилируется ...
но больше всего смущает что по идее 2,3,4,5 во втором ряду должны быть сверху, но цифры 6,7,8 из предыдущего лэйаута перерисованы явно после
Записан
Apktyc
Самовар
**
Offline Offline

Сообщений: 132


Просмотр профиля
« Ответ #3 : Декабрь 25, 2018, 00:12 »

А этот код компилируется? (2)

А выложите проект напопробовать. А, банально, пересобрать проект пробовали?

Если воспринимать предложенный текст как некий псевдокод, то вроде бы все должно работать.
Записан
dss
Гость
« Ответ #4 : Декабрь 25, 2018, 00:30 »

А этот код компилируется? (2)

А выложите проект напопробовать. А, банально, пересобрать проект пробовали?

Если воспринимать предложенный текст как некий псевдокод, то вроде бы все должно работать.

да я вроде и выложил все!
три файла :
main.cpp
test1.h
test.cpp

 если нужны картинки ,  и лень морочиться со своими образцами, то могу упаковать и выложить тут


P.S.  если что то не так делаю то сильно не пинайте . Первый пост на сайте программистов. Да и QT  только в процессе обучения . Но всегда стараюсь сам разбираться, а тут тупик.
Записан
dss
Гость
« Ответ #5 : Декабрь 25, 2018, 00:36 »

А этот код компилируется?
Смущает
Код
C++ (Qt)
firstLineLabel = new QLabel();


странно (
у меня написано вот так :
   for (int i = 0; i < 11; i++)
      firstLineLabel[ i ] = new QLabel();

но когда копировал в первый пост скобка i скобка исчезли ( видать курсив от этого пошел )
Записан
dss
Гость
« Ответ #6 : Декабрь 25, 2018, 00:38 »

Код:
#pragma once
#include "test1.h"
 #include <QtWidgets/QApplication>
 

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

QApplication a(argc, argv);
test1 *w = new test1;

w->setGeometry(400, 100, 700, 500);

init_test();

w->show();

return a.exec();
}

Записан
dss
Гость
« Ответ #7 : Декабрь 25, 2018, 00:40 »

test1.h
Код:
#pragma once

#include <QtWidgets/QMainWindow>
#include <qdialog>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>

void init_test();

class test1 : public QDialog
{
Q_OBJECT
public:
test1(QWidget *parent = Q_NULLPTR);

QLabel *firstLineLabel[11]; // место под картинки первого ряда
QHBoxLayout *firstLinelayout;

QLabel *secondLineLabel[11]; // место под картинки 2 ряда
QHBoxLayout *secondLinelayout ;

QLabel *firstCount;
QLabel *secondCount;


QPushButton *push1;      // кнопки
QPushButton *push2;
QPushButton *push3;
QPushButton *push4;
QPushButton *push5;

QVBoxLayout *mainlayout;

void  Show_(QString deck[],int a, int b ) // формируем 1й лєйаут и 2й  
{

while ((firstLinelayout->takeAt(0)) != 0)
{
// удаляет все єлементі из лайаута
}
firstLinelayout->addStretch(1);

for (int i = 0; i < a; i++)
{
firstLineLabel[i]->setPixmap(QPixmap(deck[i]));
firstLinelayout->addWidget(firstLineLabel[i]);
};

firstLinelayout->addStretch(1);
firstCount->setText(QString::number(a));
firstLinelayout->addWidget(firstCount);


while ((secondLinelayout->takeAt(0)) != 0)
{
// удаляет все єлементі из лайаута
}

secondLinelayout->addStretch(1);
for (int i = 0; i < b; i++)
{
secondLineLabel[i]->setPixmap(QPixmap(deck[i+ 26]));
secondLinelayout->addWidget(secondLineLabel[i]);
};

secondLinelayout->addStretch(1);
secondCount->setText(QString::number(b));
secondLinelayout->addWidget(secondCount);



}


public slots:
void push1Slot();  
void push2Slot();
void push3Slot();
void push4Slot();
void push5Slot();

private:

};


test1.cpp
Код:
#include "test1.h"
#include <QString>
#include <QVBoxLayout>
#include <QHBoxLayout>
 
using namespace std;
int count1Line = 0;
int count2Line = 0;
QString  deck[52];

test1::test1(QWidget *parent)
: QDialog(parent)
{
for (int i = 0; i < 11; i++)
firstLineLabel[i] = new QLabel();

firstLinelayout = new QHBoxLayout;

for (int i = 0; i < 11; i++)
secondLineLabel[i] = new QLabel();

secondLinelayout = new QHBoxLayout;

firstCount = new QLabel();
secondCount = new QLabel();

push1 = new QPushButton(" +1 pic 1st Line ");
push2 = new QPushButton(" clear 1st Line ");
push3 = new QPushButton(" +1 pic 2st Line ");
push4 = new QPushButton(" clear 2st Line ");
push5 = new QPushButton("  Random  ");

QHBoxLayout *pushlayout = new QHBoxLayout;
pushlayout->addWidget(push1);
pushlayout->addWidget(push2);
pushlayout->addWidget(push3);
pushlayout->addWidget(push4);
pushlayout->addWidget(push5);

mainlayout = new QVBoxLayout;
mainlayout->addLayout(firstLinelayout);
mainlayout->addLayout(secondLinelayout);
mainlayout->addLayout(pushlayout);
setLayout(mainlayout);

connect(push1, SIGNAL(clicked()), this, SLOT(push1Slot()));
connect(push2, SIGNAL(clicked()), this, SLOT(push2Slot()));
connect(push3, SIGNAL(clicked()), this, SLOT(push3Slot()));
connect(push4, SIGNAL(clicked()), this, SLOT(push4Slot()));
connect(push5, SIGNAL(clicked()), this, SLOT(push5Slot()));

}

void test1::push1Slot() // добавляем 1 картинку в 1ю линию
{
count1Line++;
if (count1Line > 10) count1Line = 10;
Show_(deck,count1Line, count2Line);
}
void test1::push2Slot() // очищаем 1ю линию
{
count1Line=0;
Show_(deck,count1Line, count2Line);
}
void test1::push3Slot()// добавляем 1 картинку в 2ю линию
{
count2Line++;
if (count2Line > 10) count2Line = 10;
Show_(deck, count1Line, count2Line);
}
void test1::push4Slot() // очищаем 2ю линию
{
count2Line = 0;
Show_(deck, count1Line, count2Line);
}

void test1::push5Slot()  // рандомное колво картинок на каждой линии
{
count1Line = rand() % 10;
count2Line = rand() % 10;
Show_(deck, count1Line, count2Line);
}

void init_test() // создаем ссылки на картинки
{
setlocale(LC_ALL, "Russian");
int Size_;
QString Res;
char Card_Mast[] = { 's' , 'c', 'd', 'h' };
char Card_nominal[] = { '2','3','4','5','6','7','8','9','T','J','Q','K','A' };

for (int i = 0; i < 4; i++)
for (int j = 0; j < 13; j++)  
{
Size_ = i * 13 + j;
Res = ":/test1/Resources/";
Res.append(Card_nominal[j]);
Res.append(Card_Mast[i]);
Res.append(".png");

deck[Size_] =   Res;
}

}
« Последнее редактирование: Декабрь 25, 2018, 00:42 от dss » Записан
Apktyc
Самовар
**
Offline Offline

Сообщений: 132


Просмотр профиля
« Ответ #8 : Декабрь 25, 2018, 01:25 »

Собрал (Qt 5.10.1) и запустил (со своими картинками) - все работает как надо. Если быстро кликать - иногда заметно как компоновщик не успевает, и на доли секунды возникает ситуация как на второй картинке, но все быстро исправляется.

Попробуйте пересобрать проект (rebuild), а заодно можно понавтыкать при обновлении qDebug() и посмотреть, сколько в компоновщике виджетов в это время (ну либо под отладчиком посмотреть).

« Последнее редактирование: Декабрь 25, 2018, 01:27 от Apktyc » Записан
dss
Гость
« Ответ #9 : Декабрь 25, 2018, 11:34 »

Собрал (Qt 5.10.1) и запустил (со своими картинками) - все работает как надо. Если быстро кликать - иногда заметно как компоновщик не успевает, и на доли секунды возникает ситуация как на второй картинке, но все быстро исправляется.

Попробуйте пересобрать проект (rebuild), а заодно можно понавтыкать при обновлении qDebug() и посмотреть, сколько в компоновщике виджетов в это время (ну либо под отладчиком посмотреть).



спасибо, что хоть постарались вникнуть . Что реально у Вас при нажатии кнопки "рандом" при смене большего числа картинок на меньшее не прорисовываются старые ? странно ...

пересборка ничего не изменила (Qt 5.11.2). Как сделать что бы не прорисовывались картинки которых уже нет в лэйауте я придумал ( перед вызовом цикла takeAt  я  присваиваю всему массиву картинок ""), Но проблема не решена - очевидно что прорисовываются картинки которых нет в текущем лэйауте ( но они там были раньше).

Я далек от мысли что ошибка разработчиков , наверняка косяк мой, но понять где я ошибся так и не смог .
Записан
Apktyc
Самовар
**
Offline Offline

Сообщений: 132


Просмотр профиля
« Ответ #10 : Декабрь 25, 2018, 13:25 »

я  присваиваю всему массиву картинок ""

Ага, закоментил этот фикс, и "ошибка" воспроизвелась.

Суть такова, удаление виджета (QLabel) из компоновщика (QHBoxLayout) на видимость самого виджета не влияет никак, сам компоновщик только располагает виджеты относительно родительского. Поэтому эти "призраки" и продолжают отрисовываться - они исключены из компоновки, но все еще продолжают быть дочерними к окну, которое их и рисует. Поэтому "удаляемые" виджеты надо либо отвязать от родителя (setParent(nullptr)), либо скрыть (hide() - потом надо будет проявить через show()).

Вы используете rand, но не инициализируете ГСЧ с помощью srand.

И еще, подозреваю, что есть утечка памяти, т.к. вызывается addStretch, а потом он просто выкидывается через takeAt без удаления.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.105 секунд. Запросов: 22.