質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

Q&A

1回答

1350閲覧

onTimerのスロットが無い、とエラーが出る

退会済みユーザー

退会済みユーザー

総合スコア0

Qt

QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

0グッド

0クリップ

投稿2019/05/24 02:48

下記のコードを実行すると、次のようなエラーが出てしまいます。

11:41:05: Starting C:\Users\user\Documents\Qt\build-BreakingBlocks-Desktop_Qt_5_12_3_MSVC2017_64bit-Debug\debug\BreakingBlocks.exe ...

QObject::connect: No such slot QWidget::onTimer() in ..\BreakingBlocks\mainwidget.cpp:11
QObject::connect: (receiver name: 'widget')
11:41:10: C:/Users/user/Documents/Qt/build-BreakingBlocks-Desktop_Qt_5_12_3_MSVC2017_64bit-Debug/debug/BreakingBlocks.exe exited with code 0

どうやら、注目すべきは、

No such slot QWidget::onTimer() in ..\BreakingBlocks\mainwidget.cpp:11

(receiver name: 'widget')

この辺りかと思うのですが、解決方法が分かりません。
どうかご教授お願い致します。

Qt

1//mainwidget.h 2#ifndef MAINWIDGET_H 3#define MAINWIDGET_H 4 5#include <QWidget> 6 7namespace Ui { 8class MainWidget; 9} 10 11class MainWidget : public QWidget 12{ 13 Q_OBJECT 14 15public: 16 explicit MainWidget(QWidget *parent = nullptr); 17 ~MainWidget(); 18 19private: 20 Ui::MainWidget *ui; 21 class QTimer *m_timer; 22}; 23 24#endif // MAINWIDGET_H 25
//mainwidget.cpp #include "mainwidget.h" #include "ui_mainwidget.h" #include <QtWidgets> MainWidget::MainWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MainWidget) { ui->setupUi(this); m_timer = new QTimer(); connect(m_timer, SIGNAL(timeout()), ui->widget, SLOT(onTimer())); m_timer->start(20); // 50/sec } MainWidget::~MainWidget() { delete ui; }
//blockscreen.h #ifndef BLOCKSCREEN_H #define BLOCKSCREEN_H #include <QWidget> class BlockScreen : public QWidget { Q_OBJECT public: explicit BlockScreen(QWidget *parent = nullptr); enum{ SCREEN_WIDTH = 320, SCREEN_HEIGHT = 480, WALL_WIDTH = 10, // 壁の幅 PAD_WIDTH = 4, // パッドの厚さ PAD_LENGTH = 32, // パッドの長さ BALL_RADIUS = 4, // ボール半径 INIT_BALL_DX = 2, // 初期ボール速度 INIT_BALL_DY = -4, BLOCK_WIDTH = 30, // ブロック幅 BLOCK_HEIGHT = 14, // ブロック高さ N_ROW_BLOCK = 7, // ブロック段数 N_COLUMN_BLOCK = (SCREEN_WIDTH - WALL_WIDTH *2) / BLOCK_WIDTH, // 1行のブロック個数 N_ROW_SPACE = 3, // 画面上部空白段数 BLOCK_Y = WALL_WIDTH + N_ROW_SPACE * BLOCK_HEIGHT, // ブロック描画位置 }; QSize sizeHint() const { return QSize(SCREEN_WIDTH, SCREEN_HEIGHT); } protected: void paintEvent(QPaintEvent *event); void iterateBall(); void reflectByWall(); // 壁による反射 void iteratePad(); void reflectByPad(); // ボールをパッドで打った場合 private: int m_ballX; // ボール中心座標 int m_ballY; int m_ballDx; // ボール速度/20msec int m_ballDy; int m_padX; // パッド左端座標 bool m_block[N_ROW_BLOCK][N_COLUMN_BLOCK]; // true for ブロック有り signals: void ballLoss(); // ボールを逃した場合 public slots: void onTimer(); }; #endif // BLOCKSCREEN_H
//blockscreen.cpp #include "blockscreen.h" #include <QtWidgets> BlockScreen::BlockScreen(QWidget *parent) : QWidget(parent) { m_ballX = SCREEN_WIDTH / 2; m_ballY = SCREEN_HEIGHT - PAD_WIDTH - BALL_RADIUS; m_ballDx = INIT_BALL_DX; m_ballDy = INIT_BALL_DY; m_padX = SCREEN_WIDTH / 2 - PAD_LENGTH / 2; for(int i = 0; i < N_ROW_BLOCK; ++i) for(int k = 0; k <N_COLUMN_BLOCK; ++k) m_block[i][k] = true; } void BlockScreen::paintEvent(QPaintEvent *event) { QPainter painter(this); QRect r = rect(); //壁部分描画 painter.setPen(Qt::black); painter.setBrush(Qt::black); painter.drawRect(0, 0, WALL_WIDTH, r.height()); painter.drawRect(r.width() - WALL_WIDTH, 0, WALL_WIDTH, r.height()); painter.drawRect(0, 0, r.width(), WALL_WIDTH); //ブロック部分描画 painter.setPen(Qt::black); //painter.setBrush(Qt::yellow); int y = BLOCK_Y; for(int i = 0; i < N_ROW_BLOCK; ++i){ // ブロックに段ごとに虹色カラーを設定 if(i == 0) painter.setBrush(QColor("#E60012")); // 赤 if(i == 1) painter.setBrush(QColor("#F39800")); // 橙 if(i == 2) painter.setBrush(QColor("#FFF100")); // 黄 if(i == 3) painter.setBrush(QColor("#009944")); // 緑 if(i == 4) painter.setBrush(QColor("#0068B7")); // 青 if(i == 5) painter.setBrush(QColor("#1D2088")); // 藍 if(i == 6) painter.setBrush(QColor("#920783")); // 紫 //} //for(int i = 0; i < N_ROW_BLOCK; ++i){ int x = WALL_WIDTH; for(int k = 0; k < N_COLUMN_BLOCK; ++k){ if(m_block[i][k]) // ブロックが有る場合 painter.drawRect(x, y, BLOCK_WIDTH, BLOCK_HEIGHT); x += BLOCK_WIDTH; } y += BLOCK_HEIGHT; } // ボール描画 painter.setPen(Qt::black); painter.setBrush(Qt::green); painter.drawEllipse(m_ballX - BALL_RADIUS, m_ballY - BALL_RADIUS, BALL_RADIUS * 2, BALL_RADIUS * 2); painter.drawRect(m_ballX, m_ballY, BALL_RADIUS, BALL_RADIUS); // パッド描画 painter.setBrush(Qt::blue); painter.drawRect(m_padX, SCREEN_HEIGHT - PAD_WIDTH, PAD_LENGTH, PAD_WIDTH); } void BlockScreen::onTimer() { iteratePad(); // パッド位置更新 iterateBall(); // ボール移動処理 update(); // 画面無効化 } void BlockScreen::iterateBall() { // ボール座標更新処理: m_ballX += m_ballDx; m_ballY += m_ballDy; reflectByWall(); reflectByPad(); } void BlockScreen::reflectByWall() { // 上の壁による反射 if( m_ballY < WALL_WIDTH + BALL_RADIUS){ m_ballY = (WALL_WIDTH + BALL_RADIUS) * 2 - m_ballY; m_ballDy = -m_ballDy; QApplication::beep(); } // 左右の壁による反射 if( m_ballX < WALL_WIDTH + BALL_RADIUS){ m_ballX = (WALL_WIDTH + BALL_RADIUS) * 2 - m_ballX; m_ballDx = -m_ballDx; QApplication::beep(); }else if( m_ballX > SCREEN_WIDTH - WALL_WIDTH - BALL_RADIUS){ m_ballX = (SCREEN_WIDTH - WALL_WIDTH - BALL_RADIUS) * 2 - m_ballX; m_ballDx = -m_ballDx; QApplication::beep(); } } void BlockScreen::iteratePad() { // パッド位置更新 m_padX = mapFromGlobal(QCursor::pos()).x() - PAD_LENGTH / 2; if(m_padX < WALL_WIDTH) m_padX = WALL_WIDTH; else if( m_padX + PAD_LENGTH > SCREEN_WIDTH - WALL_WIDTH) m_padX = SCREEN_WIDTH - WALL_WIDTH - PAD_WIDTH; } void BlockScreen::reflectByPad() { if( m_ballY > SCREEN_HEIGHT - PAD_WIDTH){ if( m_ballX >= m_padX && m_ballX + PAD_LENGTH){ // パッドに当たった場合(パッド端でのボール半径は無視) m_ballY = (SCREEN_HEIGHT + BALL_RADIUS) * 2 - m_ballY; m_ballDy = -m_ballDy; }else{ emit ballLoss(); } } }
//main.cpp #include "mainwidget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWidget w; w.show(); return a.exec(); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

こんにちは。

ui->widgetをBlockScreenへ「格上げ」すればOKです。
手元ではそれっぽい画面が表示され、ボールが動きました。

投稿2019/05/24 03:29

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/05/24 04:44

ありがとうございます。 また、padに当たった時の処理ですがこのままですとおそらく左端のみpadの座標が指定されていて、右端が指定されていないのでボールがpadの右を通過して落下する処理が施されていません。 この問題を解決するにはどの部分を直せばよいでしょうか?
Chironian

2019/05/24 05:06

主旨が大きく異なりますので、新たに質問を立てた方が良いと思います。
退会済みユーザー

退会済みユーザー

2019/05/24 06:14

ありがとうございます。 解決しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問