Проблема с QScrollArea
06.10.2011, 18:21. Показов 3123. Ответов 1
Доброго времени суток.
Пишу Game of life. Собственно, простенькая реализация логики на консоли есть, решил перенести её на GUI. До некоторых пор все было хорошо, пока не столкнулся со ScrollArea. Большую часть кода писал почти полностью с книги М. Саммерфилда. "Qt4", и вот, что получилось.
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| //gamemap.h
#ifndef GAMEMAP_H
#define GAMEMAP_H
#include <QWidget>
#include <QColor>
class GameMap : public QWidget
{
Q_OBJECT
public:
GameMap(QWidget *parent = 0);
~GameMap();
//void setRows(const int r) { rows = r; }
//void setColumn(const int c) { columns = c; }
void clearMap();//k
QSize sizeHint() const;
//bool getPause() const { return pause; }
//int getSize() const { return size; }
void step();
protected:
void paintEvent(QPaintEvent *event);//k
void mousePressEvent(QMouseEvent *event);//k
void mouseMoveEvent(QMouseEvent *event);//k
void showEvent(QShowEvent *event);//k
void timerEvent(QTimerEvent *event);//k
void hideEvent(QHideEvent *event);//k
private:
bool **mainMap;
bool **auxiliaryMap;
int rows;
int columns;
int size;//size of cell's home
QColor curCellColor;
bool pause;
int myTimerId;
int time;
void setCell(const QPoint &pos, bool alive);//k
};
#endif // GAMEMAP_H |
|
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
| //gamemap.cpp
#include <QtGui>
#include <gamemap.h>
#define LEFT_DOWN mainMap[r + 1][c - 1] ////////////////////////////////////
#define DOWN mainMap[r + 1][c] //[-1 L_U -1] [-1 U 0] [-1 R_U +1]//
#define RIGHT_DOWN mainMap[r + 1][c + 1] //[0 L -1] [0^__^0] [0 R +1]//
#define RIGHT mainMap[r][c + 1] //[+1 L_D -1] [+1 D 0] [+1 R_D +1]//
#define RIGHT_UP mainMap[r - 1][c + 1] ////////////////////////////////////
#define UP mainMap[r - 1][c]
#define LEFT_UP mainMap[r - 1][c - 1]
#define LEFT mainMap[r][c - 1]
GameMap::GameMap(QWidget *parent) : QWidget(parent)
{
rows = 100;
columns = 100;
mainMap = new bool* [rows];
auxiliaryMap = new bool* [rows];
for(int r = 0; r < rows; ++r)
{
mainMap[r] = new bool [columns];
auxiliaryMap[r] = new bool [columns];
}
clearMap();
curCellColor = Qt::black;
size = 50;
myTimerId = 0;
time = 100;
pause = true;
}
GameMap::~GameMap()
{
for(int r = 0; r < rows; ++r)
{
delete[] mainMap[r];
delete[] auxiliaryMap[r];
}
delete[] mainMap;
delete[] auxiliaryMap;
}
QSize GameMap::sizeHint() const
{
return QSize(columns * size - 1, rows * size - 1);
}
void GameMap::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(Qt::black);
for(int r = 0; r <= rows; ++r)
painter.drawLine(0, size * r, size * columns, size * r);
for(int c = 0; c <= columns; ++c)
painter.drawLine(size * c, 0, size * c, size * rows);
painter.setBrush(QBrush(curCellColor, Qt::SolidPattern));
for(int r = 0; r < rows; ++r)
for(int c = 0; c < columns; ++c)
if(mainMap[r][c])
painter.drawEllipse((r * size) + 3, (c * size) + 3, size - 6, size - 6);
}
void GameMap::mousePressEvent(QMouseEvent *event)
{
if(event -> button() == Qt::LeftButton)
setCell(event -> pos(), true);
else if(event -> button() == Qt::RightButton)
setCell(event -> pos(), false);
}
void GameMap::mouseMoveEvent(QMouseEvent *event)
{
if(event -> buttons() & Qt::LeftButton)
setCell(event -> pos(), true);
else if(event -> buttons() & Qt::RightButton)
setCell(event -> pos(), false);
}
void GameMap::showEvent(QShowEvent*)
{
myTimerId = startTimer(time);
}
void GameMap::timerEvent(QTimerEvent *event)
{
if(event -> timerId() == myTimerId)
step();
else
QWidget::timerEvent(event);
}
void GameMap::hideEvent(QHideEvent*)
{
killTimer(myTimerId);
}
void GameMap::clearMap()
{
for(int r = 0; r < rows; ++r)
for(int c = 0; c < columns; ++c)
if(mainMap[r][c])
mainMap[r][c] = 0;
update();
}
void GameMap::step()
{
for(int r = 0; r < rows; ++r)
for(int c = 0; c < columns; ++c)
{
int neighbors = 0;
if((r == 0) && (c == 0)) //left up
neighbors += DOWN + RIGHT_DOWN + RIGHT;
else if((r == 0) && (c == (columns - 1))) //right up
neighbors += LEFT + LEFT_DOWN + DOWN;
else if((r == (rows - 1)) && (c == (columns - 1))) //right down
neighbors += UP + LEFT_UP + LEFT;
else if((r == (rows - 1)) && (c == 0)) //left down
neighbors += RIGHT + RIGHT_UP + UP;
else if(c == 0) //left
neighbors += DOWN + RIGHT_DOWN + RIGHT + RIGHT_UP + UP;
else if(r == 0) //up
neighbors += LEFT + LEFT_DOWN + DOWN + RIGHT_DOWN + RIGHT;
else if(c == (columns - 1)) //right
neighbors += UP + LEFT_UP + LEFT + LEFT_DOWN + DOWN;
else if(r == (rows - 1)) //down
neighbors += RIGHT + RIGHT_UP + UP + LEFT_UP + LEFT;
else
neighbors += LEFT_DOWN + DOWN + RIGHT_DOWN + RIGHT + RIGHT_UP + UP + LEFT_UP + LEFT;
if(mainMap[r][c])
((neighbors > 3) || (neighbors < 2)) ? auxiliaryMap[r][c] = false :
auxiliaryMap[r][c] = true;
else
(neighbors == 3) ? auxiliaryMap[r][c] = true :
auxiliaryMap[r][c] = false;
}
for(int r = 0; r < rows; ++r)
for(int c = 0; c < columns; ++c)
mainMap[r][c] = auxiliaryMap[r][c];
update();
}
void GameMap::setCell(const QPoint &pos, bool alive)
{
int r = pos.x() / size,
c = pos.y() / size;
mainMap[r][c] = alive;
update();
} |
|
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| //mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "gamemap.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(); //k
~MainWindow(); //k
GameMap *map;
protected:
void closeEvent(QCloseEvent *event); //k
private slots:
void newGame(); //k
/*void openMap();
bool saveMap();
bool saveMapAs();*/
void about(); //k
private:
void createActions(); //k
void createMenus(); //k
//void createContextMenu();
//void createToolBars();
//void createStatusBar();
//void writeSettings();
//void readSettings();
bool okToContinue(); //k
//bool loadMap(const QString &fileName);
//bool saveMap(const QString &fileName);
//void setCurrentMap(const QString &fileName);
QMenu *fileMenu;
QMenu *optionsMenu;
QMenu *helpMenu;
QToolBar *fileToolBar;
QAction *newAction, //k
//QAction *openAction; //k
//QAction *saveAction; //k
//QAction *saveAsAction; //k
//QAction *closeAction; //k
QAction *exitAction; //k
};
#endif // MAINWINDOW_H |
|
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
| #include <QtGui>
#include "mainwindow.h"
#include "gamemap.h"
MainWindow::MainWindow()
{
map = new GameMap;
setCentralWidget(map);
createActions();
createMenus();
//createContextMenu();
//createToolBars();
//createStatusBar();
//readSettings();
setWindowIcon(QIcon(":/images/icon.bmp"));
}
MainWindow::~MainWindow()
{
delete map;
delete newAction;
delete exitAction;
}
void MainWindow::newGame()
{
if(okToContinue())
map -> clearMap();
}
void MainWindow::about()
{
QMessageBox::about(this, tr("About Game of Life"),
tr("<h2>Game of Life 0.0.1 (a)</h2>"
"<br>All rights reserved. Maybe... :)"));
}
void MainWindow::createActions()
{
newAction = new QAction(tr("&New"), this);
newAction -> setIcon(QIcon(":images/new.bmp"));
newAction -> setShortcut(tr("Ctrl + N"));
newAction -> setStatusTip(tr("Begin a new game"));
connect(newAction, SIGNAL(triggered()), this, SLOT(newGame()));
/*openAction = new QAction(tr("&Open"), this);
openAction -> setIcon(QIvon(":/images/open.bmp"));
openAction -> setShortcut(tr("Ctrl + O"));
openAction -> setStatusTip(tr("Open the map"));
connect(openAction, SIGNAL(triggered()), this, SLOT(openMap()));
saveAction = new QAction(tr("&Save"), this);
saveAction -> setIcon(QIvon(":/images/save.bmp"));
saveAction -> setShortcut(tr("Ctrl + S"));
saveAction -> setStatusTip(tr("Save the map"));
connect(saveAction, SIGNAL(triggered()), this, SLOT(saveMap()));
saveAsAction = new QAction(tr("&Save as"), this);
saveAsAction -> setIcon(QIvon(":/images/save_as.bmp"));
saveAsAction -> setStatusTip(tr("Save the map as..."));
connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveMapAs()));*/
/*closeAction = new QAction(tr("&Close"), this);
closeAction -> setShortcut(tr("Ctrl + W"));
closeAction -> SetStatusTip(tr("Close this map"));
connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));*/
exitAction = new QAction(tr("E&xit"), this);
exitAction -> setShortcut(tr("Ctrl + Q"));
exitAction -> setStatusTip(tr("Exit the application"));
connect(exitAction, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
}
void MainWindow::createMenus()
{
fileMenu = menuBar() -> addMenu(tr("&File"));
fileMenu -> addAction(newAction);
//fileMenu -> addAction(closeAction);
fileMenu -> addSeparator();
fileMenu -> addAction(exitAction);
//optionsMenu = menuBar() -> addMenu(tr("&Options"));
//optionsMenu
}
bool MainWindow::okToContinue() //need files
{
/*for(int row = 0; row < rows; ++row)
for(int column = 0; column < columns; ++column)
if(mainMap[row][column])
{
int warning = QMessageBox::warning(this, tr("Game of Life"),
tr("The map has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Yes | QMessageBox::Default,
QMessageBox::No,
QMessageBox::Cansel | QMessageBox::Escape);
if(warning == QMessageBox::Yes)
return saveMap();
else if(warning == QMessageBox::Cansel)
return false;
else
return true;
}*/
return true; //don't remove
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(okToContinue())
{
//writeSettings
event -> accept();
}
else
event -> ignore();
} |
|
| C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| #include <QtGui/QApplication>
#include <QScrollArea>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow *mainW = new MainWindow;
//QScrollArea *scroll = new QScrollArea;
//scroll -> setWidget(mainW -> map);
//scroll -> showMaximized();
mainW -> showMaximized();
return a.exec();
} |
|
Что я хочу от этого кода. Я хочу, чтобы добавились полосы прокрутки и, чтобы при прокрутке полоса главного меню оставалась на месте. Если убрать комментарии в main, то будет просто поле со скроллбарами, без полоски главного меню(что, в принципе, логично). Если сделать setWidget(mainW), то поле будет прокручиваться вместе с полосой главного меню(что тоже, наверное, предсказуемо). В общем, куда я только не запихивал ScrollArea, нигде она вменяемо работать не хочет.
В процессе тестирования обнаружился неприятный баг. Если прокрутить поле до конца вправо, зажать любую клавишу мыши и сдвинуть мышь до упора вправо, то программа вылетает. Почему так, понять не могу, объясните, пожалуйста, если знаете.
Также буду рад увидеть комментарии по поводу кода.
ps/Большая часть кода не реализована, поскольку без ScrollArea не будет иметь никакого смысла.
0
|