QObject: Cannot create children for a parent that is in a different thread for QActionGroup
-
Hi,
I'm using QActionGroup to implement a feature in the qt based media player I'm developing. I'm using it to build a display/ select functionality of the available audio tracks just as in standard vlc player, but I'm getting following error. I'm not using QThread explicitly in my code
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QActionGroup(0x8a539e8), parent's thread is QThread(0x8740aa8), current thread is QThread(0xa832dae0) -
Hi,
Maybe just a thought, but debug your application and set breakpoints in your code here and there. Then you can check out the thread window of the debugger (you should see at least 1 as MainWindow/Gui). That might give a clue.
Do you include other libraries? Those might generate threads on there own. Maybe post some code that contains the place where the error is given??
No it's just guessing were to go ;-) -
@@Hi,
Thanks for the response. I'm including libvlc and many Qt widget applications. I did not receive any warning or error so far. It started with the implementation of QactionGroup based functions that was used to select audio and video tracks. I have included the relevant parts. Even with this warning the functionality behaves as epected, but my concern is it OK to leave this warning message ? Or a way to get rid of it if not.
I have following files
Mwindow.cpp (all the media player functions included here)
Mwindow.h
main.cpp
Tracks.cpp ( handling track related info)
Tracks.h
ui_Mwindow.h (Qt interface related stuff)- Mwindow.cpp *
#include <QtGui/QFileDialog>
#include <QtGui/QInputDialog>
#include <vlc/vlc.h>
#include <QtGui>
#include <QStyle>
#include <QDesktopWidget>
#include <QDBusMessage>
#include <QDBusConnection>
#include <QFileInfo>
#include <QtGui/QActionGroup>
#include <QtGui/QMenu>
#include <fstream>
#include <string.h>
#include <iostream>
#include <stdio.h>
#include "Mwindow.h"
#include "ui_Mwindow.h"
#include "Tracks.h"#define qtu( i ) ((i).toUtf8().constData())
Mwindow::Mwindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::Mwindow) {this->ui->setupUi(this);
....
initUI();
}Mwindow::~Mwindow() {
if (vlcInstance)
libvlc_release (vlcInstance);
delete ui;
}void Mwindow::initUI() {
this->buildAudioMenu();
QObject::connect(this->ui->OpenFile, SIGNAL(triggered()), this,
SLOT(openFile()));
....
}void Mwindow::openFile() {
....
}
....void Mwindow::vlcEvent(const libvlc_event_t* event, void* vlcvideo_object) {
....
if (event->type == libvlc_MediaPlayerPlaying) {
player->gatherTracks();
player->updateMenu();
}
}// and many functions like above, but no errors or warnings. All started with this part
void Mwindow::buildAudioMenu() {
m_audioMenu = this->ui->menubar->addMenu(tr("Audio"));
m_audioTracksMenu = m_audioMenu->addMenu(tr("Tracks"));
m_audioTracksActionGroup = new QActionGroup(this);
m_audioTracksActionGroup->setExclusive(true);
connect(m_audioTracksActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(audioTrackSelected(QAction*)));
}int Mwindow::audioTrackCount() const {
return libvlc_audio_get_track_count(vlcPlayer);
}bool Mwindow::hasAudio() const {
return audioTrackCount();
}const QList<Tracks> &Mwindow::audioTracks() const {
return m_audioTracks;
}int Mwindow::audioTrackIndex() const {
return libvlc_audio_get_track(vlcPlayer);
}void Mwindow::setAudioTrack(int newTrackIndex) {
if (newTrackIndex != audioTrackIndex()) {
libvlc_audio_set_track(vlcPlayer, newTrackIndex);
emit audioTrackChanged(newTrackIndex);
}
}void Mwindow::gatherTracks() {
if (!libvlc_media_player_is_playing(vlcPlayer))
return;m_audioTracks.clear();
m_videoTracks.clear();if (hasAudio() && m_audioTracks.isEmpty()) {
int index = 0;
libvlc_track_description_t *trackDescription =
libvlc_audio_get_track_description(vlcPlayer);
while (trackDescription) {
m_audioTracks.append(
Tracks(trackDescription->i_id, index, Tracks::Audio,
QString::fromUtf8(trackDescription->psz_name)));
trackDescription = trackDescription->p_next;
index++;
}
}}
void Mwindow::audioTrackSelected(QAction *action) {
if (vlcPlayer) {
setAudioTrack(action->data().toInt());
}
}void Mwindow::updateMenu() {
if (!vlcPlayer || !libvlc_media_player_is_playing(vlcPlayer))
return;m_audioTracksMenu->clear();
m_audioTracksActionGroup->actions().clear();
m_audioTracksMenu->setEnabled(hasAudio());
foreach (Tracks track, audioTracks()) {
QAction *action = m_audioTracksActionGroup->addAction(track.name());
action->setCheckable(true);
action->setData(track.id());
if (track.id() == audioTrackIndex()) {
action->setChecked(true);
}
m_audioTracksMenu->addAction(action);
}}
- Mwindow.h *
#ifndef MWINDOW_H_
#define MWINDOW_H_#include <QtGui>
#include <vlc/vlc.h>
#include <kplotobject.h>
#include <keditlistwidget.h>class Tracks;
namespace Ui {
class Mwindow;
}class Mwindow: public QMainWindow {
Q_OBJECT
public:
explicit Mwindow(QWidget *parent = 0);
~Mwindow();
.....
int audioTrackCount() const;
bool hasAudio() const;
const QList<Tracks> & audioTracks() const;
int audioTrackIndex() const;signals:
.....
void audioTrackChanged(int audioTrackIndex);public slots:
.....
void setAudioTrack(int newTrackIndex);
void updateMenu();private slots:
.....
void gatherTracks();
void audioTrackSelected(QAction * action);protected:
.....
virtual void closeEvent(QCloseEvent*);private:
.....
static void vlcEvent(const libvlc_event_t* event, void* vlcvideo_object);
QList<Tracks> m_audioTracks;
QMenu *m_audioMenu;
QMenu *m_audioTracksMenu;
QActionGroup *m_audioTracksActionGroup;
void buildAudioMenu();
void initUI();};
#endif //MWINDOW_H_
@@@@
-
Hi,
It seems to me that you try to create a new QActionGroup (this) when the function buildAudioMenu is called. Maybe do a if (m_audioTracksActionGroup == NULL) before allocating the memory again, but that is just trivial.
Just looking at your code I can't see real big issues and thread problems.
What happens if you remove the this pointer as parent of the QActionGroup?
I do think it has to do with the VLC included memory and usage.