Results 1 to 10 of 10

Thread: GUI Thread is not safe

  1. #1
    Join Date
    Oct 2016
    Posts
    5

    Default GUI Thread is not safe

    Hello all,

    My program executes and works with sockets and all, although I get an error; QPixmap: It is not safe to use pixmaps outside the GUI thread. But the thing is that I'm not even using QPixmap? Also, can this be the problem that my update wont trigger the paintEvent?
    Here is the code:

    Qt Code:
    1. #include "mainwindow.h"
    2. #include <QApplication>
    3. #include <stdio.h>
    4. #include <sys/types.h>
    5. #include <sys/socket.h>
    6. #include <netdb.h>
    7. #include <cstring>
    8. #include <stdlib.h>
    9. #include <vector>
    10. #include <pthread.h>
    11. #include <string>
    12. #include <iostream>
    13. #include <X11/Xlib.h>
    14. #include "msg.h"
    15. #define NUM_THREADS 1
    16. using namespace std;
    17.  
    18. class ConnectionVar{
    19. public:
    20. int socket;
    21. int seq;
    22. int playerID;
    23. int x = 0;
    24. int y = 0;
    25. };
    26. class players{
    27. public:
    28. int playerID;
    29. int x = 0;
    30. int y = 0;
    31. };
    32.  
    33. ConnectionVar var;
    34.  
    35. void sendInitMessage(){
    36. int results;
    37. var.seq = 0;
    38. JoinMsg join;
    39. join.head.id = 0;
    40. join.head.seq_no = var.seq;
    41. join.head.type = Join;
    42. join.head.length = sizeof(join);
    43.  
    44. var.seq = var.seq + 1;
    45. char sendBuffer[sizeof(join)];
    46.  
    47. memcpy((void*)sendBuffer, (void*)&join, sizeof(join));
    48. results = send(var.socket, sendBuffer, sizeof(sendBuffer), 0);
    49.  
    50. }
    51.  
    52. void *recvieveMsg(void *arg){
    53. int results;
    54. MainWindow mw;
    55. vector<players> pl;
    56. char recBuffer[1024];
    57. while(1){
    58. results = recv(var.socket, recBuffer, sizeof(recBuffer), 0);
    59. printf("Something recieved");
    60. if(results > 0){
    61. MsgHead* msghead;
    62. msghead = (MsgHead*)recBuffer;
    63. if(msghead->type == Join){
    64. var.playerID = msghead->id;
    65. printf("%d", var.playerID);
    66. }else if(msghead->type == Leave){
    67. printf("LEAVE!!\n");
    68. }else if(msghead->type == Change){
    69. ChangeMsg* changemsg;
    70. changemsg = (ChangeMsg*)recBuffer;
    71. if(changemsg->type == NewPlayer){
    72. NewPlayerMsg* newPlayer;
    73. newPlayer = (NewPlayerMsg*)recBuffer;
    74. if(msghead->id != var.playerID){
    75. players *player = new players();
    76. player->playerID = msghead->id;
    77. pl.push_back(*player);
    78. }
    79. }else if(changemsg->type == PlayerLeave){
    80. printf("Player Leave");
    81. }else if(changemsg->type == NewPlayerPosition){
    82. NewPlayerPositionMsg* newPos;
    83. newPos = (NewPlayerPositionMsg*)recBuffer;
    84. if(msghead->id == var.playerID){
    85. var.x = newPos->pos.x;
    86. var.y = newPos->pos.y;
    87. //mw.pos(1, 1);
    88. }else{
    89. for(int i=0;i<pl.size();i++){
    90. if(pl.at(i).playerID == msghead->id){
    91. pl.at(i).x = newPos->pos.x;
    92. pl.at(i).y = newPos->pos.y;
    93. }
    94. }
    95. }
    96. cout << "Pos" << newPos->pos.x << " "<<newPos->pos.y <<endl;
    97. }else{
    98. printf("Change msg went wrong");
    99. }
    100. }else if(msghead->type == Event){
    101. printf("Event!!\n");
    102. }else if(msghead->type == TextMessage){
    103. printf("TextMessage!!\n");
    104. }else{
    105. printf("What was that?");
    106. }
    107. }else if(results == 0){
    108. printf("Connection closed!!!");
    109. break;
    110. }else{
    111. printf("Something went wrong");
    112. break;
    113. }
    114. fflush(stdout);
    115. }
    116. }
    117.  
    118. void sendMessage(char* s, MsgType type){
    119. std::cout << s << endl;
    120. if(type == Event){
    121. MoveEvent ev;
    122. ev.event.type = Move;
    123. ev.event.head.id = var.playerID;
    124. ev.event.head.seq_no = var.seq;
    125. ev.event.head.type = Event;
    126. if(strcmp(s, "Left") == 0){
    127. ev.pos.x = var.x -1;
    128. ev.pos.y = var.y;
    129. }else if(strcmp(s, "Right") == 0){
    130. ev.pos.x = var.x + 1;
    131. ev.pos.y = var.y;
    132. }else if(strcmp(s, "Up") == 0){
    133. ev.pos.x = var.x;
    134. ev.pos.y = var.y -1;
    135. }else if(strcmp(s, "Down") == 0){
    136. ev.pos.x = var.x;
    137. ev.pos.y = var.y + 1;
    138. }else{
    139. std::cout << "Something wrong" << endl;
    140. }
    141. ev.event.head.length = sizeof(ev);
    142.  
    143. char sendBuffer[sizeof(ev)];
    144. memcpy((void*)sendBuffer, (void*)&ev, sizeof(ev));
    145.  
    146. send(var.socket, sendBuffer, sizeof(sendBuffer), 0);
    147. }
    148.  
    149. }
    150.  
    151.  
    152.  
    153. void connection(){
    154. int socket, results;
    155.  
    156.  
    157.  
    158. struct addrinfo *serverInfo, hints;
    159. memset(&hints, 0, sizeof(hints));
    160. hints.ai_family = AF_UNSPEC;
    161. hints.ai_socktype = SOCK_STREAM;
    162.  
    163. results = getaddrinfo("localhost", "49152", &hints, &serverInfo);
    164. if(results != 0){
    165. printf("getaddrinfo went wrong");
    166. exit(1);
    167. }
    168.  
    169. socket = ::socket(serverInfo->ai_family, serverInfo->ai_socktype, serverInfo->ai_protocol);
    170. var.socket = socket;
    171. results = connect(socket, serverInfo->ai_addr, serverInfo->ai_addrlen);
    172. if(results == -1){
    173. printf("Could not connect");
    174. exit(1);
    175. }
    176. freeaddrinfo(serverInfo);
    177.  
    178. pthread_t threads[NUM_THREADS];
    179. sendInitMessage();
    180. results = pthread_create(&threads[0], NULL, recvieveMsg, NULL);
    181.  
    182. }
    183.  
    184. void startGame(){
    185.  
    186. connection();
    187. }
    188.  
    189.  
    190.  
    191. int main(int argc, char *argv[])
    192. {
    193. XInitThreads();
    194. QApplication a(argc, argv);
    195. MainWindow w;
    196. w.show();
    197. return a.exec();
    198. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. #include "mainwindow.h"
    2. #include "msg.h"
    3. #include "ui_mainwindow.h"
    4. #include <QKeyEvent>
    5. #include <QPainter>
    6. #include <QWidget>
    7.  
    8. MainWindow::MainWindow(QWidget *parent) :
    9. QMainWindow(parent),
    10. ui(new Ui::MainWindow)
    11. {
    12. ui->setupUi(this);
    13. gameStatus = false;
    14. }
    15.  
    16. MainWindow::~MainWindow()
    17. {
    18. delete ui;
    19. }
    20.  
    21. void MainWindow::on_connect_clicked()
    22. {
    23. ui->connect->setEnabled(false);
    24. ui->disconnect->setEnabled(true);
    25. gameStatus = true;
    26. startGame();
    27. }
    28.  
    29. void MainWindow::keyPressEvent(QKeyEvent *event){
    30. if(gameStatus){
    31. switch(event->key()){
    32. case Qt::Key_Left:
    33. sendMessage("Left", Event);
    34. break;
    35. case Qt::Key_Right:
    36. sendMessage("Right", Event);
    37. break;
    38. case Qt::Key_Up:
    39. sendMessage("Up", Event);
    40. break;
    41. case Qt::Key_Down:
    42. sendMessage("Down", Event);
    43. break;
    44. default:
    45. event->ignore();
    46. break;
    47. }
    48.  
    49. }
    50. }
    51.  
    52. void MainWindow::paintEvent(QPaintEvent *e){
    53. printf("SDA");
    54. fflush(stdout);
    55. if(gameStatus){
    56. QPainter painter(this);
    57. painter.drawLine(115, 115, 5, 5);
    58. }
    59.  
    60.  
    61. }
    62.  
    63. void MainWindow::updateEvent(){
    64. printf("SAJDIDAS");
    65. fflush(stdout);
    66. this->update();
    67. }
    68.  
    69. void MainWindow::pos(int x, int y){
    70. this->updateEvent();
    71. }
    72.  
    73. /*
    74. void MainWindow::on_disconnect_clicked()
    75. {
    76.  
    77. }
    78. */
    To copy to clipboard, switch view to plain text mode 

    (the printf is just for me seeing that the function actually calling which it does when I'm moving the mouse over my button but not when updateEvent is called.)

    Thanks for all help!

  2. #2
    Join Date
    Mar 2008
    Location
    Kraków, Poland
    Posts
    1,536
    Thanked 284 Times in 279 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: GUI Thread is not safe

    Problem is line 54 in function recvieveMsg(void *arg).

  3. #3
    Join Date
    Oct 2016
    Posts
    5

    Default Re: GUI Thread is not safe

    Uhm okay, why is that a problem and how would you fix it?

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: GUI Thread is not safe

    Quote Originally Posted by bds View Post
    Uhm okay, why is that a problem and how would you fix it?
    You are either accidentally calling recvieveMsg from a secondary thread or you are accidentally using UI objects like MainWindow in there.

    Any specific reason you need to use native thread API and native socket API other than making your life more complicated?

    Cheers,
    _

  5. #5
    Join Date
    Oct 2016
    Posts
    5

    Default Re: GUI Thread is not safe

    Well, our teacher thought it was funny to give us an assignment in C++ although the course is in Java. So we had a week on us learning C++ and I developed first in g++ terminal compiler before using native thread/socket API.

  6. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: GUI Thread is not safe

    Ah, then using Qt from the beginning would have been a lot easier.

    I moved from Java to C++ because Qt gave me such a similar experience.

    So you likely don't need any threads at all, Qt's sockets, unlike Java's, works nicely with the main event loop.

    If you prefer keeping the thread, make sure you don't access any UI objects from secondary threads.

    Cheers,
    _

  7. #7
    Join Date
    Oct 2016
    Posts
    5

    Default Re: GUI Thread is not safe

    Ah okay. But the thing is, how can I update the GUI in my thread without calling the GUI thread? Can I use some Observers, like in Java, or do you have any good way to go?

  8. #8
    Join Date
    Mar 2008
    Location
    Kraków, Poland
    Posts
    1,536
    Thanked 284 Times in 279 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: GUI Thread is not safe

    Read about signals and slots.

  9. #9
    Join Date
    Oct 2016
    Posts
    5

    Default Re: GUI Thread is not safe

    I'm not really following signals and slots. So in my function *recvieveMessage(), and I want to connected it to MainWindow:os, can I use connection this way; connection(recieveMessage(), x, MainWindow:os, x);? Because I read that it has to be an object, and my recvieveMessage is not an object.

  10. #10
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: GUI Thread is not safe

    QWidget::pos() is a "getter" so you unlikely want to call this, you probably meant "move".

    QWidget::move() is not a slot, but of yours you could create one with matching arguments in your calls.

    You can't use a function as a sender object, the type of the first argument of QObject::connect() is "QObject*", i.e. a pointer to a QObject.

    You can, however, call a slot by name using QMetaObject::invokeMethod()
    Qt Code:
    1. QMetaObject::invokeMethod(receiver, "slotname", Qt::QueuedConnection, ....);
    To copy to clipboard, switch view to plain text mode 
    Where "...." is any arguments you want to pass.

    Cheers,
    _

Similar Threads

  1. Thread safe or not
    By raj_iv in forum Qt Programming
    Replies: 1
    Last Post: 19th January 2013, 21:28
  2. Replies: 5
    Last Post: 7th February 2012, 22:13
  3. thread-safe
    By babymonsta in forum Qt Programming
    Replies: 0
    Last Post: 5th May 2010, 10:18
  4. About the QSound,is thread safe?
    By cspp in forum Qt Programming
    Replies: 0
    Last Post: 6th November 2009, 14:26
  5. Is a QProcess thread safe in Qt4?
    By Jay_D in forum Qt Programming
    Replies: 4
    Last Post: 1st September 2009, 16:38

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.