前提・実現したいこと
QtのGUIのラベルに、文字列AAAと文字列BBBを交互に表示するアプリを、C++で作っています。
文字列AAAと文字列BBBは、水平スライダー(horizontalSlider)の値を更新間隔としています。
文字列を交互に表示する処理は、メインの処理からスレッドを分岐させて実現しています。
水平スライダーが変更されたら、その値を、グローバル変数(変数名during)に格納します。
文字列を交互に表示する処理は、無限ループで、duringを参照し続けます。
duringは、ふたつのスレッドから参照されるので、mutexで保護しています。
問題点
コンパイルエラーは出力されないのですが、実行すると、
数秒間、水平スライダーは反応せず、
その後、反応したかと思うと、また反応しなくなったりします。
ラベルの表示も、滑らかに更新されず、固まったりします。
水平スライダーの値に応じて、更新間隔は変更されているのですが・・。
エラーメッセージなどは、出力されていないように思います。
該当のソースコード
【言語】C++
【ツールキット】Qt
ソースコード
問題のないmain()などの処理は省略します。
MainWindowクラスは他のメソッドからインスタンス化されます。
■■■■■■■■■■■
■ MainWindow.cpp ■
■■■■■■■■■■■
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <iostream>
#include <thread>
#include <mutex>
//ミューテックス
std::mutex mtx;
//更新間隔
int during;
//━━━━━━━━━━━━━━━━━━━━━
// 文字列を交互に表示する処理
// (クラスには属していないメソッドです)
// (引数*uiは現在使用していないので無視して下さい)
//━━━━━━━━━━━━━━━━━━━━━
void play(Ui::MainWindow *ui)
{
for(;;){
ui->label_forPlay->setText("AAA");
mtx.lock();
std::this_thread::sleep_for(std::chrono::milliseconds(during));
mtx.unlock();
ui->label_forPlay->setText("BBB");
mtx.lock();
std::this_thread::sleep_for(std::chrono::milliseconds(during));
mtx.unlock();
}
return;
}
//━━━━━━━━━━━━━━━━━━━━━
// MainWindowクラスのコンストラクタ
//━━━━━━━━━━━━━━━━━━━━━
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), //親クラスの初期化
ui(new Ui::MainWindow) //メンバ(ui_mainwindow.h)を実体化
{
//各ウィジェットを実体化
ui->setupUi(this);
//水平スライダー変更時、更新間隔を変更 connect(ui->horizontalSlider, SIGNAL(sliderReleased()), this, SLOT(hSliderReleased())); //新しいスレッドで、文字列を交互に表示する処理 std::thread thr_play(play, ui); thr_play.detach();
}
//━━━━━━━━━━━━━━━━━━━━━
// 水平スライダー変更時のSLOT
//━━━━━━━━━━━━━━━━━━━━━
void MainWindow::hSliderReleased(){
mtx.lock();
during = (ui->horizontalSlider->value() * 50);
mtx.unlock();
return;
}
■■■■■■■■■■
■ MainWindow.h ■
■■■■■■■■■■
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <thread>
//━━━━━━━━━━━━━━━━━━━━━
// ui_mainwindow.hのなかで規定されてる
//━━━━━━━━━━━━━━━━━━━━━
namespace Ui {
class MainWindow;
}
//━━━━━━━━━━━━━━━━━━━━━
// MainWindowクラス
//━━━━━━━━━━━━━━━━━━━━━
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
//コンストラクタ
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow *ui;
private slots:
// 水平スライダー変更時のSLOT
void hSliderReleased();
};
試したこと
connectとhSliderReleased()を使ってduringを変更するのではなく
playメソッドが水平スライダーの値を直接参照するようにして実行したら
水平スライダーとラベルは停止することなく、滑らかに表示されるようになりました。
この方法で問題点は解消されるのですが、
connectとhSliderReleased()を使ってduringを変更する方法を採用したいのです。
補足情報(FW/ツールのバージョンなど)
【OS】Ubuntu 18.04
【開発環境】Qt Creator 4.6.2 Based on Qt 5.10.1

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/08/14 03:15 編集