Skip to content

General and Desktop

This is where all the desktop OS and general Qt questions belong.
83.6k Topics 457.7k Posts
  • Using Apples Information Property List Files (Info.plist) in Python on MacOS

    Unsolved
    7
    0 Votes
    7 Posts
    4k Views
    R
    I have the same exact issue right now. PySide6 devs are blaming Cpython for this and they suggested re-building Cpython for scratch with cusotm info.plist. This looks tedious to me. https://bugreports.qt.io/browse/PYSIDE-2474
  • QMultiMedia thumbnail extraction

    Unsolved
    1
    0 Votes
    1 Posts
    191 Views
    No one has replied
  • QValueAxis how to set label fixsize with blank space

    Unsolved qchart
    1
    0 Votes
    1 Posts
    321 Views
    No one has replied
  • SystemTrayIcon context menu doesn't want to hide - properly implemented Tray Icon

    Unsolved
    5
    1 Votes
    5 Posts
    811 Views
    V
    Hi, I tried to follow this video, and the problem solved: https://www.youtube.com/watch?v=WbDRtK1melU
  • External Variables not transferring

    Unsolved
    2
    0 Votes
    2 Posts
    175 Views
    JonBJ
    @thinkingcow I think you can find more information for the "fix available" by hovering over the warning message or clicking something. Anyway, data.h declares that there are two global variables somewhere, x and y (btw really bad names for global variables). But in fact no such global variables are actually defined anywhere in your code (might be in a data.cpp but you don't show any such file). And the 2 extern variables are not referenced anywhere. networkplot::networkplot has its own extern statement for them, main() defines an x & y but they are local variables, not globals. You may be new to C++ but presumably not to C, else you would likely not know about extern. So the code question you have is really about C rather than C++. Don't use any extern here, you don't need it. By the look of things, pass x & y as parameters from where they are defined in main() to your networkplot class instance. Probably as extra parameters to the constructor. Or via a separate method, plot(), which you call after construction that does just the ui->customplot->graph(0)->setData(x,y); part.
  • The text drawn by paint scrolls with the scroll bar

    Unsolved
    2
    0 Votes
    2 Posts
    212 Views
    K
    @Nan-Feng Hello Did you find the answer? I have the same issue and do not know how to fix it
  • VLC QT loop

    Solved
    2
    0 Votes
    2 Posts
    178 Views
    C
    @Service-IT Wait until the player signals that the playback is ended, seek to zero in the media or load the media again, and play.
  • 0 Votes
    3 Posts
    739 Views
    J
    @Bonnie Thank you for the reply. Since my last post, I made some significant progress by debugging the Windows Qt multimedia source. I swapped QBuffer for a QRingBuffer. As it turns out, the performance issues were not related to the QBuffer in my previous implementation, however I prefer to use a lighter weight object as the Single Producer Single Consumer (SPSC) buffer between the microphone (the default input device) and the speaker (the default output device). The remaing problem that I need help with is how to schedule a restart after I encounter a buffer underrun or Eof condition (where there are no bytes available in the SPSC buffer). I swapped QBuffer for Qt's private QRingBuffer class which is used in other multimedia QIODevice derived objects. This class is not really well documented but it is relatively straight forward to understand - this link shows the impmentation). The ring buffer is basically made up from a list of RingChunks - each of which is effectively a wrapper around a QByteArray (with supporting head and tail offsets). The problem now is that I once the pull mode AudioSink encounters an error in its timer callback method - in this case the pullSource method (see below for Qt's windows AudioSink implementation) (QWindowsAudioSink::pullSource), the audio output changes its state to QAudio::IdleState with QAudio::IOError or QAudio::UnderrunError, and stops the pull timer. The pull timer callback is resposible for requesting the next raw chunk of audio from the QRingBuffer via the m_pullSource->read(readLen)) and writing it to the speaker ourput device. Meanwhile the capture slot in my worker thread keeps appending microphone data to this shared mpSinkDevice - so the buffer keeps growing (which would prevent the buffer underrun/eof condition) but I have no idea how to restart the audio output. void RtpWorker::handleAudioAvailable(const QAudioBuffer& rAudioBuffer) const { // append captured audio to mpSinkDevice's QRingBuffer mpSinkDevice->write(rAudioBuffer.constData< const char>(), rAudioBuffer.byteCount()); } The m_pullSource field in the code below is a pointer to the QIODevice containing the QRingBuffer which was opened for Read/Write (write is required by the audio capture slot to copy the raw audio from the microphone to the QRingBuffer). void QWindowsAudioSink::pullSource() { qCDebug(qLcAudioOutput) << "Pull source"; if (!m_pullSource) return; auto bytesAvailable = m_pullSource->isOpen() ? qsizetype(m_pullSource->bytesAvailable()) : 0; auto readLen = qMin(bytesFree(), bytesAvailable); if (readLen > 0) { QByteArray samples = m_pullSource->read(readLen); if (samples.size() == 0) { deviceStateChange(QAudio::IdleState, QAudio::IOError); return; } else { write(samples.data(), samples.size()); } } auto playTimeUs = remainingPlayTimeUs(); if (playTimeUs == 0) { deviceStateChange(QAudio::IdleState, m_pullSource->atEnd() ? QAudio::NoError : QAudio::UnderrunError); } else { deviceStateChange(QAudio::ActiveState, QAudio::NoError); m_timer->start(playTimeUs / 2000); } } Here is my SinkDevice //! Modeled after the Generator class example from QT 6.x audio output example. class SinkDevice : public QIODevice { Q_OBJECT public: /** * Explicit constructor * * @param parent [in] parent. */ explicit SinkDevice(QObject* parent = nullptr) : QIODevice(parent) , mBuffer{} {} /** * Explicit constructor * * @param rByteArray [in] array of multi-channel audio * samples. * @param parent [in] parent. */ explicit SinkDevice(const QByteArray& rByteArray, QObject* parent = nullptr) : QIODevice(parent) , mBuffer{} { mBuffer.append(rByteArray); } ~SinkDevice() override = default; /** * Start the IO device - open in read/write mode * so it can act like a ring buffer. */ void start(); /** * Close IO device. */ void stop(); //! Audio device should give sequential access [[nodiscard]] bool isSequential() const override { return true; } [[nodiscard]] qint64 bytesAvailable() const override { return mBuffer.size() + QIODevice::bytesAvailable(); } // Our size [[nodiscard]] qint64 size() const override { return mBuffer.size(); } protected: [[nodiscard]] qint64 readData(char* data, qint64 maxlen) override; [[nodiscard]] qint64 writeData(const char* data, qint64 maxlen) override; private: // disable copy & move semantics on QObject subclasses // https://www.cleanqt.io/blog/why-qobject-subclasses-are-not-copyable Q_DISABLE_COPY_MOVE(SinkDevice) void generateData(const QAudioFormat& format, qint64 durationUs, int sampleRate); QRingBuffer mBuffer; };
  • Can not create/use DLL

    Unsolved
    28
    0 Votes
    28 Posts
    2k Views
    SGaistS
    @JacobNovitsky as I wrote: check that you are properly exporting stuff from your library code.
  • This topic is deleted!

    Unsolved
    1
    0 Votes
    1 Posts
    27 Views
    No one has replied
  • Qt6 thread error

    Unsolved
    5
    0 Votes
    5 Posts
    805 Views
    S
    @Christian-Ehrlicher I'm sorry that I may misunderstand your meaning. Here's the PlayerWidget class, still works well in Qt 6.3.2 and 5.14.2, but can't work in Qt 6.5.3. playerwidget.h: #ifndef PLAYERWIDGET_H #define PLAYERWIDGET_H #define Multimedia_And_Widgets_Enabled #define Multimedia_Private_Enabled #include <QWidget> #include <QLabel> #include <QFileInfo> #include <QKeyEvent> #ifdef Multimedia_And_Widgets_Enabled #include <QImageWriter> #include <QCamera> #include <QMediaPlayer> #include <QVideoWidget> #include <QMediaMetaData> #include <QVideoFrame> #include <QGraphicsVideoItem> #include <QGraphicsScene> #include <QGraphicsView> #include <QAudioOutput> #include <QMediaRecorder> #include <QAudioDecoder> #if(QT_VERSION>=QT_VERSION_CHECK(6,0,0)) #include <QVideoSink> #include <QVideoFrameFormat> #else #ifdef Multimedia_Private_Enabled #include <private/qvideoframe_p.h> #endif #include <QVideoProbe> #include <QAbstractVideoSurface> #include <QAudioRecorder> #include <QAudioEncoderSettings> #include <QVideoEncoderSettings> #endif #endif class PlayerWidget : public QWidget { Q_OBJECT public: explicit PlayerWidget(QWidget *parent = nullptr); ~PlayerWidget(); enum State { StoppedState, PlayingState, PausedState }; bool eventFilter(QObject *watched, QEvent *event); bool setFilePath(QString p); QString filePath(); QMediaPlayer* mediaPlayer(); bool play(); void pause(); void stop(); void setPosition(int position); int duration(); int volume(); void setVolume(int v); bool hasVideo(); bool hasAudio(); QVideoFrame videoFrame(); QMediaPlayer::MediaStatus mediaStatus(); PlayerWidget::State state(); void lock(); void unlock(); bool isLocked(); signals: void keyRelease(QKeyEvent* event); void error(QMediaPlayer::Error e,QString errorString); void statusChanged(QMediaPlayer::MediaStatus status); void positionChanged(int position); void durationChanged(int duration); void videoFrameChanged(QVideoFrame frame); void hasVideoChanged(bool available); void hasAudioChanged(bool available); void stateChanged(PlayerWidget::State state); void statusChanged_private(QMediaPlayer::MediaStatus status); void error_private(QMediaPlayer::Error e,QString errorString); private: QEventLoop* loop; QMediaPlayer* player; QVideoWidget* videowidget; QLabel* label; QAudioOutput* audiooutput; QVideoFrame frame; QString filepath = ""; bool videoAvailable = false; bool audioAvailable = false; bool enable = true; bool ret; bool widgetmode = false; QPoint startpoint = QPoint(-1,-1); #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) QVideoSink* sink; #else QVideoProbe* probe; #endif }; #endif // PLAYERWIDGET_H playerwidget.cpp: #include "playerwidget.h" static bool hasFilePermission(QString filepath,QIODevice::OpenModeFlag device = QIODevice::ReadWrite) { bool check = true; if(filepath != "") { QFile* file = new QFile(filepath); if(!file->exists()) check = false; if(file->open(device)) { file->close(); delete file; if(!check) QFile::remove(filepath); return true; } else { delete file; return false; } } else { return false; } } PlayerWidget::PlayerWidget(QWidget *parent) : QWidget(parent) { qDebug() << "thread of playerwidget.cpp : " << this->thread(); this->setStyleSheet("background-color: black;"); this->setAttribute(Qt::WA_AcceptTouchEvents, true); player = new QMediaPlayer; videowidget = new QVideoWidget(this); audiooutput = new QAudioOutput; label = new QLabel(this); loop = new QEventLoop(this); #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) sink = new QVideoSink; #else probe = new QVideoProbe; #endif label->setStyleSheet("background-color: black;"); label->resize(this->size()); label->setAlignment(Qt::AlignCenter); if(widgetmode) { videowidget->show(); label->hide(); } else { videowidget->hide(); label->show(); } player->setVideoOutput(videowidget); #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) player->setAudioOutput(audiooutput); player->setVideoSink(sink); #else probe->setSource(player); #endif this->installEventFilter(this); #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) connect(player,&QMediaPlayer::errorChanged,[this](){ emit error_private(player->error(),player->errorString()); emit error(player->error(),player->errorString()); }); connect(player,&QMediaPlayer::hasVideoChanged,[this](){ videoAvailable = player->hasVideo(); emit hasVideoChanged(videoAvailable); if(this->hasVideo()) { label->show(); } else { label->clear(); label->hide(); } }); connect(player,&QMediaPlayer::hasAudioChanged,[this](){ audioAvailable = player->hasAudio(); emit hasAudioChanged(audioAvailable); if(this->hasVideo()) { label->show(); } else { label->clear(); label->hide(); } }); connect(player,&QMediaPlayer::playbackStateChanged,[this](){ emit stateChanged(this->state()); }); connect(sink,&QVideoSink::videoFrameChanged,[this](const QVideoFrame &f){ frame = f; emit videoFrameChanged(frame); if(f.isValid() && widgetmode == false && !this->isLocked()) { label->setPixmap(QPixmap::fromImage(f.toImage().scaled(label->size(),Qt::KeepAspectRatio))); } }); #else QObject::connect(player,QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error),[=](){ emit error_private(player->error(),player->errorString()); emit error(player->error(),player->errorString()); }); QObject::connect(player,QOverload<bool>::of(&QMediaPlayer::videoAvailableChanged),[=](bool available){ videoAvailable = available; emit hasVideoChanged(videoAvailable); if(this->hasVideo()) { label->show(); } else { label->clear(); label->hide(); } }); QObject::connect(player,QOverload<bool>::of(&QMediaPlayer::audioAvailableChanged),[=](bool available){ audioAvailable = available; emit hasAudioChanged(audioAvailable); if(this->hasVideo()) { label->show(); } else { label->clear(); label->hide(); } }); QObject::connect(probe,QOverload<const QVideoFrame &>::of(&QVideoProbe::videoFrameProbed),[=](const QVideoFrame &f){ frame = f; emit videoFrameChanged(frame); if(f.isValid() && enable == true && widgetmode == false) { QImage image = qt_imageFromVideoFrame(f); #ifdef Q_OS_WIN image = image.mirrored(); #endif if(!image.isNull()) { image = image.scaled(label->size(),Qt::KeepAspectRatio); label->setPixmap(QPixmap::fromImage(image)); } } }); QObject::connect(player,QOverload<QMediaPlayer::State>::of(&QMediaPlayer::stateChanged),[=](){ emit stateChanged(this->state()); }); #endif connect(player,&QMediaPlayer::mediaStatusChanged,[this](){ emit statusChanged_private(player->mediaStatus()); emit statusChanged(player->mediaStatus()); }); connect(player,&QMediaPlayer::positionChanged,[this](){ emit positionChanged(player->position()); }); connect(player,&QMediaPlayer::durationChanged,[this](){ emit durationChanged(player->duration()); }); } bool PlayerWidget::eventFilter(QObject *watched, QEvent *event) { if(watched == this) { if(event->type() == QEvent::KeyRelease) { QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); emit keyRelease(keyEvent); } else if(event->type() == QEvent::Resize) { if(widgetmode) videowidget->resize(this->size()); else label->resize(this->size()); } else if(event->type() == QEvent::Close) { player->stop(); } else if(event->type() == QEvent::Hide) { if(widgetmode) videowidget->hide(); else label->hide(); } else if(event->type() == QEvent::Show) { if(widgetmode) videowidget->show(); else label->show(); } } return QObject::eventFilter(watched,event); } PlayerWidget::~PlayerWidget() { } bool PlayerWidget::setFilePath(QString p) { if(QFileInfo(p).isFile() && hasFilePermission(p,QIODevice::ReadOnly)) { filepath = p; #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) player->setSource(QUrl::fromLocalFile(filepath)); #else player->setMedia(QUrl::fromLocalFile(filepath)); #endif return true; } else { filepath = ""; return false; } } QString PlayerWidget::filePath() { return filepath; } QMediaPlayer* PlayerWidget::mediaPlayer() { return player; } bool PlayerWidget::play() { //QEventLoop* loop = new QEventLoop; player->play(); QObject::connect(this,QOverload<QMediaPlayer::Error,QString>::of(&PlayerWidget::error_private),[=](QMediaPlayer::Error error,QString string){ if(error != QMediaPlayer::Error::NoError) { this->disconnect(this,SIGNAL(error_private(QMediaPlayer::Error,QString)),0,0); filepath = ""; loop->quit(); //loop->exit(0); } }); QObject::connect(this,QOverload<QMediaPlayer::MediaStatus>::of(&PlayerWidget::statusChanged_private),[=](QMediaPlayer::MediaStatus status){ if(status == QMediaPlayer::BufferedMedia) { this->disconnect(this,SIGNAL(statusChanged_private(QMediaPlayer::MediaStatus)),0,0); loop->quit(); //loop->exit(0); } }); this->lock(); loop->exec(); this->unlock(); return bool(player->error()==QMediaPlayer::Error::NoError); } void PlayerWidget::pause() { player->pause(); } void PlayerWidget::stop() { player->stop(); } void PlayerWidget::setPosition(int position) { if(position >= 0) player->setPosition(position); } int PlayerWidget::duration() { return player->duration(); } int PlayerWidget::volume() { #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) return int(player->audioOutput()->volume()*100.0); #else return player->volume(); #endif } void PlayerWidget::setVolume(int v) { #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) player->audioOutput()->setVolume(float(v)/100.0); #else player->setVolume(v); #endif } bool PlayerWidget::hasVideo() { //return player->hasVideo(); return videoAvailable; } bool PlayerWidget::hasAudio() { //return player->hasAudio(); return audioAvailable; } QVideoFrame PlayerWidget::videoFrame() { return frame; } QMediaPlayer::MediaStatus PlayerWidget::mediaStatus() { return player->mediaStatus(); } PlayerWidget::State PlayerWidget::state() { #if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) if(player->playbackState() == QMediaPlayer::PlaybackState::PlayingState) { return PlayerWidget::State::PlayingState; } else if(player->playbackState() == QMediaPlayer::PlaybackState::PausedState) { return PlayerWidget::State::PausedState; } else { return PlayerWidget::State::StoppedState; } #else if(player->state() == QMediaPlayer::State::PlayingState) { return PlayerWidget::State::PlayingState; } else if(player->state() == QMediaPlayer::State::PausedState) { return PlayerWidget::State::PausedState; } else { return PlayerWidget::State::StoppedState; } #endif } void PlayerWidget::lock() { enable = false; } void PlayerWidget::unlock() { enable = true; } bool PlayerWidget::isLocked() { if(enable == true) return false; else return true; } how to use: PlayerWidget* widget = new PlayerWidget(this); if(widget->setFilePath(QFileDialog::getOpenFileName()) && widget->play()) { return true; } else { return false; }
  • Qt5 new signals-slots syntax does not work [SOLVED]

    11
    0 Votes
    11 Posts
    28k Views
    J
    I know this is quite old, but if someone ends up here again, this is the up-to-date way of defining an overload when connecting an overloaded signal: QOverload<int>::of(&QComboBox::currentIndexChanged)
  • Qt6 source code installation problem

    Unsolved
    4
    0 Votes
    4 Posts
    1k Views
    R
    @jsulm now understood why response is slow to various questions as it dependent on user volunteering to answer.
  • How to call a QProperty binding from a subclass?

    Unsolved
    5
    0 Votes
    5 Posts
    316 Views
    K
    @jsulm I have found a "better way" using QMetaObject::invokeMethod and i also can get the return value of the function! There's any "cons" in calling functions with invokeMethod?
  • Time critical execution and QThread

    Solved
    4
    0 Votes
    4 Posts
    349 Views
    S
    The important thing to have in mind is the cache. It sounds like you have a vector of pointers. One problem with this is that when you iterate of the vector you won't necessarily access adjacent memory. This will totally screw with cache performance. Even if you were to get a huge slice of memory for your thread this slice would still be internally fragmented. On the other hand, if you were to use a regular vector of objects (instead of pointers) it will screw with you real time requirement. Occasionally, you'll have a resize of the vector which will copy all of its data which will slow it down. Only if you can make sure there is no resize happening (as you said you are swapping things out) this could work. Otherwise you need to find some middle ground: something like chunks of memory linked together such that each chunk with several objects/values fits into a cache line (maybe the size of a L2 cache line). And finally, the most important advice: Use profiling to measure where your performance bottleneck is to optimize in areas where it is actually necessary and helpful.
  • Qt 6.5.3 : Can't change QWidget position

    Solved qwidget position geometry
    6
    0 Votes
    6 Posts
    1k Views
    P
    @JonB @JoeCFD OK found that Wayland just doesn't allow to windows to move themselves. Not a necessary feature for me and can't solve the black screen problem when logging with Xorg. Will just ask gnome to center new windows with tweaks. Closing the topic. Thanks to both you.
  • LTS Query

    Unsolved
    2
    0 Votes
    2 Posts
    154 Views
    Christian EhrlicherC
    Qt 6.3 is no LTS release, 6.2 and 6.5 are. But you can profit only when you have a commercial license.
  • Opengl undefined references with qchartview

    Unsolved
    2
    0 Votes
    2 Posts
    328 Views
    Christian EhrlicherC
    You need to link against the opengl library. see e.g. here: https://forum.qt.io/topic/84385/opengl32-lib-no-such-file-or-directory
  • This topic is deleted!

    Unsolved
    1
    0 Votes
    1 Posts
    3 Views
    No one has replied
  • How to connect signal by drug on Qt Creator signal slot editor mode?

    Solved
    3
    0 Votes
    3 Posts
    375 Views
    B
    @StudentScripter Thank you for your reply. Probably, but the problem is solved. For some reason in my environment, selecting buddy editting mode launches signal/slot editting mode. https://x.com/bigbenbigben/status/1707383342621229086?s=20