2012-05-22 4 views
2

mineSweeping 게임에서 QPushButton을 사용하고 있습니다.Qt에서 setVisble을 실행 한 직후에 다시 칠하지 마십시오.

easy 모드에서 하드 모드로 변경 한 후 QPushButton의 수가 9x9에서 30x16으로 변경됩니다.

그래서, 나는 MainWindow를의 생성자에서 GridLayout과QPushButton을 (하드 모드입니다) 가장 많은를 추가합니다.

btnArr = new QPushButton[HARD_WIDTH * HARD_HEIGHT]; // member element 
int index = 0; 
for (int i = 0; i < HARD_HEIGHT; ++i) { 
    for (int j = 0; j < HARD_WIDTH; ++j) { 
     ui->mainGrid->addWidget(&btnArr[index], i, j, 1, 1, 
           Qt::AlignCenter); 
     ++index; 
    } 
} 

은 다음 사용자 변경 모드 (하드 모드로 예컨대 : 쉬운 모드), resetBtn(HARD_WIDTH, HARD_HEIGHT);가 호출 될 경우.

void MainWindow::resetBtn(const int width, const int height) 
{ 
    int index = 0; 
    for (int i = 0; i < HARD_HEIGHT; ++i) { 
     for (int j = 0; j < HARD_WIDTH; ++j) { 
      if (j < width && i < height) { 
       btnArr[index].setVisible(true); 
      } else { 
       btnArr[index].setVisible(false); 
      } 
      ++index; 
     } 
    } 
} 

문제

는 위젯이 setVisible를 호출 할 때마다 페인트 다시 보인다는 것이다. 그래서 하드 모드의 경우 30x16 번 호출되어 다음과 같은 이상한 결과를 초래합니다. enter image description here

그래서이 루프 중에 다시 그리지 않는 위젯을 어떻게 설정할 수 있습니까?

미리 감사드립니다.

답변

1

QPushButton의 총 수는 정말 큰 : 30x16 = 480! 저는 사람들이 프로그래밍 로직을 변경하도록 사용하지 않지만이 경우에는 QPushButton을 사용하는 것이 더 나은 방법이 아니라고 생각합니다. 레이아웃은 오브젝트가 추가 될 때 오브젝트를 이동 시키려 할 때 정말로 힘든 시간을 가져야하며, 리프레시 할 수있는 리프레시 시간의 내부 제한에 도달하고있는 것일 수 있습니다.

내가 한 것은 사용자 지정 paintEvent 메서드가있는 사용자 지정 위젯입니다. 여기서 너비와 높이를 원하는 열과 행의 수로 나눌 수 있고 게임이 진행되는 동안 pixmaps로 셀을 페인트 할 수 있습니다.

마우스 상호 작용의 경우 mousePressEvent을 그리드의 마우스 위치를 계산하고 해당 메서드를 호출하거나 이벤트의 위치를 ​​나타내는 신호를 내보내는 사용자 지정 논리로 무시하는 것이 가장 좋습니다. 코드 작성이 그리 어렵지 않습니다. event->buttons() 메서드를 사용하여 어떤 마우스 버튼을 눌렀는지 알 수 있으며 원하는 경우 다른 신호를 낼 수 있습니다.

전체 프로그램을 변경하는 것이 더 낫다고 대답하는 데는 사용하지 않지만이 경우에는 "어려운 방법"이라고 생각합니다. 나는 이것이 당신이 찾고있는 대답이 아니라는 것을 알고 있지만,이 가능성을 고려하십시오.

+0

합리적인 것 같습니다. 고마워요! – Ovilia

1

"위대한"변경을 수행하기 전에 상위 위젯에서 setUpdatesEnabled(false)을 호출 해보고 모두 시도한 후에 다시 사용하도록 설정할 수 있습니다.

+0

그들 중 부모 위젯은'setUpdatesEnabled (false)'메소드를 가지고 있지 않은 gridWidget입니다. gridWidget의 상위 위젯은 MainWindow입니다. 나는 그것에 노력했지만 아무것도 바뀌지 않았다. – Ovilia

+0

QWidget에서 파생 된 모든 객체에는 해당 메서드가 있습니다. Qt의 어떤 버전을 사용하고 있습니까? – Mat

+0

이것은 QGridLayout의 인스턴스이며 QWidget에서 파생되지 않습니다. MinGW 4.4 컴파일러에서 Qt 버전은 4.7.4입니다. – Ovilia

1

아마 내가 틀렸을 수도 있지만, Qt는 setVisible()이 호출 된 직후 위젯을 렌더링하지 않는다는 것을 알고 있습니다. 렌더링은 render()를 수동으로 호출하는 경우를 제외하고는 'render'이벤트의 결과로 발생합니다.

Qt는 또한 하나에 여러 페인트 이벤트를 를 병합하여 그림을 속도를 시도 : 공식 Qt는 문서 (http://qt-project.org/doc/qt-4.8/qwidget.html#paintEvent)에서

. update()가 여러 번 호출되거나 윈도우 시스템 이 여러 페인트 이벤트를 보내는 경우 Qt는 이러한 이벤트를 큰 영역 (QRegion :: united() 참조)과 함께 하나의 이벤트로 병합합니다. repaint() 함수는 이 최적화를 허용하지 않으므로 이 가능할 때마다 update()를 사용하는 것이 좋습니다.

필자의 본능은 레이아웃이 아닌 (하드 모드에서 모든 버튼을 표시 할 공간이 충분하지 않음) 페인팅 문제가 아니라고합니다. 또한 레이아웃에 단추를 추가 할 때 Qt :: AlignCenter를 사용하지 말아야한다고 생각합니다. 레이아웃의 모든 단추를 가운데에 맞 춥니 다. 레이아웃의 부모 위젯을 중앙화하고 (생성하고 중심화하지 않는 경우) 배치 정책을 올바르게 설정해야합니다 (QWidget setSizePolicy). 이건 정말 (setUpdatesEnabled이 문제가 해결되는지 @Mat의 솔루션 동의하시기 바랍니다) 당신은 내가 당신이하려고하는 생각

1

(/는 false) setUpdatesEnabled를 사용할 수있는 회화에 문제가있는 경우

그러나 @Mat 같은

제안 잘못된 문제를 해결하십시오. 이런 위젯을 업데이트해서는 안됩니다. 당신이 원한다면, 변경하기 전에 레이아웃의 부모 위젯을 숨기고 나중에 다시 보여 주어야합니다.

보다 나은 방법은 QStackedWidget을 사용하고 모든 보드를 초기에 준비하는 것입니다. 다른 보드로 전환하는 것은 단순히 활성 위젯을 전환하는 것입니다.

0

은/보이지 않는 활성화/대신 볼의 해제를 시도해보십시오

void MainWindow::resetBtn(const int width, const int height) 
{ 
    int index = 0; 
    for (int i = 0; i < HARD_HEIGHT; i++) 
     for (int j = 0; j < HARD_WIDTH; j++) 
      btnArr[index++].setEnabled(j < width && i < height); 
} 
+0

나는 이것이 내가 필요한 것이 아닌가 걱정된다. 광산 게임에 사용할 수없는 단추를 표시하는 것이 적절합니까? – Ovilia

+0

@Ovilia, 버튼 -> setFlat (true)를 호출하십시오 - 버튼이 보이지 않도록)) – k06a

관련 문제