crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

История благодарностей участнику ssoft ::: Спасибо сказали: 30 раз(а)
Дата поста: В теме: За сообщение: Спасибо сказали:
15.2.2013, 9:37 Шаблон, динамическое значения параметра шаблона
Цитата(ViGOur @ 15.2.2013, 9:58) *
Как я понимаю это из-за того, что у меня переменная создается динамически (во время выполнения), а шаблон должен быть инстанцирован статически (во время компиляции). Поправьте меня если я ошибаюсь.

И собственно вопрос, как сделать так, чтобы это работало и возможно ли это? :)
Если это не возможно, то буду думать как сделать по другому...


Имено так, шаблоны конкретизируются во время компиляции и нет возможности использовать динамически изменяющиеся параметры шаблона.
В данном случае, я подозреваю, что необходимо использовать паттерн "Фабрика".
ViGOur,
24.1.2013, 9:01 Синхронизация при сигналах и слотах в разных потоках
1. Если передача параметров происходит по значению.

signals:
    void foo ( QString );
    void foofoo ( const & QString );


то при асинхронном вызове (через очередь сообщений), передаваемые данные копируются и синхронизировать ничего не нужно.

2. Если передача параметров происходит по указателю по не константной ссылке.

signals:
    void foo ( QString * );
    void foo ( QString & );
    void foofoo ( const QString * );


то при асинхронном вызове копируется значение указателя (ссылки), за существование объекта QString и синхронизацию доступа к нему отвечает сам программист.
Алексей1153,
10.1.2013, 11:36 Удаление объекта из QList
Рекомендую использовать умные указатели, тогда вообще не нужно заморачиваться с удалениями, код будет понятнее и не будет приводить к утечкам памяти, например, в случае исключений.

Что-то вроде

    typedef QSharedPointer< MyWidget > Widget;
    myWidgetList.append( Widget( new MyWidget ) ); // добавление

    ...

    myWidgetList.removeAt( i ); // удаление

    ...

    myWidgetList.clear(); // удаление всех сразу
QMainWindow,
13.12.2012, 8:07 Проблема с вызовом дочернего окна
Нужно же указать что widget является отдельным окном, а не частью this.

Server_Settings *WindowSett = new Server_Settings(this);
WindowSett->setWindowFlags( Qt::Window );
WindowSett->show();
WinnieThePooh,
10.12.2012, 7:05 наступил на замечательные грабли
Тогда уж лучше так

//ок
for(td_map::iterator it=m.begin();it!=m.end();/*it++*/)
{
    if(it->second==2)
    {
        it = m.erase( it );
    }
    else
    {
        ++it;
    }
}


а еще лучше

inline
bool removeCondition ( const td_map::value_type & value ) { return value.second == 2; }

//....
void funct()
{
    std::remove_if( m.begin(); m.end(); removeCondition );
};

Алексей1153,
30.11.2012, 8:40 Как правильно поместить объект в поток
Для того чтобы связать два объекта из разных потоков между собой, нужно гарантировать, что объекты созданы.
Могу предложить следующую реализацию.

class CWork //класс рабочего объекта
...

class CMyThread : public QThread
{
    typedef QSharedPointer< CWork > WorkPointer;
    WorkPointer work;

public:
    CWork * workObject () const;

signals:
   void workCreated ();

};

void CMyThread::run()
{
    work = WorkPointer( new CWork() );

    emit workCreated();

    exec();
}


// применение
int main ( int argc, char ** argv )
{
    QApplication app( argc, argv );

    CMyThread thread1;
    QEventLoop loop1;
    connect( &thread1, SIGNAL( workCreated() )
        , &loop1, SLOT( quit() ) );
    tread1.start();
    // ожидаем сигнала от tread1
    loop1.exec();

    CMyThread thread2;
    QEventLoop loop2;
    connect( &thread2, SIGNAL( workCreated() )
        , &loop2, SLOT( quit() ) );
    tread2.start();
    // ожидаем сигнала от tread2
    loop2.exec();

    // соединяем на здоровье
    connect ( tread1.workObject(), SIGNAL( ... )
        , tread2.workObject(), SLOT( ... ) ) );

    return app.exec();
}


Да, и QByteArray можно передавать по значению, т.к. внутри организован указатель на данные с подсчетом ссылок, т.е. данные при передаче по значению не копируются.
mezmay,
29.11.2012, 7:18 Цикл for и подчеркивание
Это обычный цикл.
В данном случае _ это переменная такая же, как i или j и т.п.
Имя переменной может начинаться с любой буквы или знака _, а может состоять только из знака _.
Ничего нового кроме запутывания данная конструкция в себе не несет.
vankleef,
8.10.2012, 7:22 Макрос для возврата имени переменной и ее значения
Цитата(RazrFalcon @ 7.10.2012, 22:43) *
Нужен макрос для отладки, подозреваю что такой уже существует, только не могу его нагуглить.

Пример работы:
int step = 24;
DEBUG(step) // "step: 24"

Можно даже с типом переменной.

Просто писать каждый раз:
qDebug() << "step:" << step;

надоедает...


Так можно написать свой

#define MY_DEBUG( var ) qDebug() << #var << ( var );
ilyabvt, RazrFalcon,
21.8.2012, 12:15 сохранение контейнера объектов в файл
Цитата(__ilya__ @ 21.8.2012, 13:03) *
понял.
Но как мне перегрузить операторы >> и <<?
я вообще понятия не имею как и что они делать должны

QDataStream & operator << ( QDataStream & stream, const Data & value )
{
    return stream
        << value.s1
        << value.s2
        << value.s3
        << value.i1
        << value.i2
        << value.i3
        << value.d1
        << value.d2
        << value.d3;
}

QDataStream & operator >> ( QDataStream & stream, Data & value )
{
    return stream
        >> value.s1
        >> value.s2
        >> value.s3
        >> value.i1
        >> value.i2
        >> value.i3
        >> value.d1
        >> value.d2
        >> value.d3;
}


если определять члены, как приватные, то нужно еще определение

class Data
{
    friend QDataStream & operator << ( QDataStream & stream, const Data & value );
    friend QDataStream & operator >> ( QDataStream & stream, Data & value );

private:
    QString s1, s2, s3;
    int i1, i2, i3;
    double d1, d2, d3;
};


Цитата(__ilya__ @ 21.8.2012, 13:03) *
Да и вообще не понятно как мне контейнер таких структур загружать?


QDataStream stream( &device );

QVector< Data > contaner;

// чтение
stream
    >> contaner;

...

// запись
stream
    << contaner;
vinnitu, __ilya__,
18.7.2012, 7:46 Сигналы и слоты
Цитата(RaiaN @ 18.7.2012, 7:36) *
Мне нужно установить связь (а-ля connect) между своим событием и слотом. Проблема заключается в том, что я не знаю, как правильно в параметр SIGNAL передать свое событие. Мне нужно передать туда событие типа KeyPressEvent. В нем при помощи switch я определяю, какая кнопка нажата,чтобы затем выполнить нужные мне действия.
Как можно это осуществить?

То есть вот допустим есть операция

connect(leftMonthButton, SIGNAL(clicked()), this, SLOT(decrementMonth()));

Мне нужно вместо clicked() поставить свое событие, которое будет реагировать при нажатии левой стрелки.


Есть как минимум два способа:

1. Можно у своего widget декларировать сигнал leftArrowClicked(), и вызывать его при обработке события keyReleaseEvent () в случае события для кнопки Qt::Qt::Key_Left.

соединить сигнал

connect(widget, SIGNAL(leftArrowClicked()), this, SLOT(decrementMonth()));


2. Можно у своего widget декларировать сигнал keyClicked( int ), и вызывать его при обработке события keyReleaseEvent (), передавая код отжатой клавиши клавиатуры.

тогда нужно модифицировать еще и слот

connect(widget, SIGNAL(keyClicked(int)), this, SLOT(onKeyClicked( int )));



RaiaN,
31.1.2012, 13:14 Ошибка в потоках
Цитата(crashsp @ 31.1.2012, 11:17) *
Получаю вот такую ошибку
Parent is QTcpSocket(0x141adcc), parent's thread is QThread(0x6a2fa0), current thread is ServerWorker(0x141adc0)

как решить ее знаю , дело в том что приложение не падает, сокеты нормально читаюстся и пишутся , хочу узнать чем это черевато ?
на сервере стабильно 5 потоков


В данном случае сообщение полностью выглядит так.

        qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
                 "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)" )


Это значит, что происходит попытка в качестве родителя указать объект из другого потока, не из того, в котором создается данный объект.
Это чревато тем, что у объекта нет родителя => возможны утечки памяти, прямой вызов методов объекта не из своего потока может привести к фатальной ошибке.
crashsp,
24.1.2012, 7:30 VC 2005 или GDB?
Цитата(ViGOur @ 23.1.2012, 17:44) *
В нескольких я и сам знаю как, я просто было подумал, что можно запускать и отлаживать сразу несколько процессов в одной студии! :)


Так и есть.

Контекстное меню на проекте
Debug -> Start new instance

и будет вам одновременная отладка любого количества процессов в MSVS.

Другой способ - в Propities для solution выставить флаг Multiple startup projects и указать какие именно проекты нужно запускать.
F5 и все процессы запустятся на отладку одновременно.
kolofut,
23.1.2012, 13:57 VC 2005 или GDB?
Цитата(kolofut @ 22.1.2012, 19:28) *
На работе есть только Visual Studio 2005, сам я привык к Eclipse. Проект написан на плюсах, gui через gdi+. Собственно для моих задач перенести проект на gcc и gdb можно.
Но имеет ли смысл? В особенности интересует удобство отладки.
Поделитесь товарищи опытом)


Я веду разработку под разными средами и разными компиляторами одновременно (так уж сложилось).

Последнее время использую в основном QT SDK и MSVS.

И там и там есть свои преимущества и недостатки.
По моим сугубо личным ощущениям вести разработку удобнее в QT SDK, отладку и диагностику пока в MSVS (GDB не всегда справляется).
Однако у меня есть специфика отладки - одновременно в отладке участвует множество процессов.
kolofut,
23.1.2012, 13:40 почему в Qt не цикла
Цитата(__ilya__ @ 23.1.2012, 13:41) *
я не давно начал юзать Qt и не пойму как в программе все события происходят без цикла.
я работал с SDL, так-же вместе с OpenGL там сначала объявиш все переменные, а все события (обработка мыши, клавиатуры и т.п.) происходят в бесконечном цикле. обычно последний метод в теле цикла смена изображения в окне.
А в Qt этого нет, не пойму, как без цикла работает. :blink:


Цикл есть. Просто он скрыт о пользователя.
Если по простому, то все происходит так.
В приложении существует диспетчер и очередь сообщений. В очередь поступают сообщения, диспетчер в цикле последовательно их направляет для обработки соответствующим объектам. Всё.

Кстати, цикл вызывается через метод приложения - exec.
__ilya__,
26.12.2011, 7:55 Много сигналов и слотов и производительность
Цитата(hoRUS @ 24.12.2011, 12:07) *
Добрый день!
Проблема такова: имеется большое количество однотипных объектов, которые связываются с некоторым объектом-диспетчером посредством сигналов и слотов (каждый объект может иметь несколько свзей с диспетчером, одинаковые сигналы объектов соединяются с одними и теми же слотами диспетчера). В каждый момент времени активным является лишь один объект, сигналы от других объектов, если они придут, должны игнорироваться. Объекты создаются на этапе инициализации диспетчера и уничтожаются при уничтожении диспетчера.
Что лучше для производительности:

a. создать все связи при создании объектов, сразу заблокироать их с помощью blockSignals() и разблокировать по мере необходимости (при активации объекта);
b. не создавать связи при создании объектов, а каждый раз при акивации связывать объект с диспетчером с помощью connect() и удалять связь деактивируемого объекта с помощью disconnect();
c. другие варианты ?

Заранее спасибо.


Если требуется высокая производительность, тогда для Qt в порядке падения производительности.

1. Реализация взаимодействия диспетчера и объектов через элементарные указатели, при необходимости с синхронизацией через QMutex или QReadWriteLock.
2. Реализация взаимодействия диспетчера и объектов через очередь сообщений (QEvent).
3. Реализация через сигнал-слот взаимодействие.
В этом случае вариант blockSignals() предпочтительнее, т.к. connect() и disconnect() очень ресурсоемкие.
hoRUS,
23.12.2011, 7:21 сигнал readyRead()
Цитата(breeve @ 22.12.2011, 19:22) *
По идее ведь я 3 раза записал в клиенте. Соответственно на сервере должен 3 раза вызваться сигнал readyRead().


Нет, так не работает.
Количество записей в клиенте не гарантирует такое же количество на сервере. Записи могут прийти как разделенные на несколько частей, так и слитые вместе. А может быть и то и другое одновременно.
Здесь на форуме есть темы по сборке сообщений из сокета, например тут

Цитата(breeve @ 22.12.2011, 19:22) *
Объясните пожалуйста как сделать так чтобы последовательно обрабатывать: клиент записал первую порцию, и пока сервер не обработает, он не может записать следующее.


Для этого необходимо разработать протокол взаимодействия клиента и сервера. Сервер должен оповещать клиента о том, что он сообщение обработал.
breeve,
20.12.2011, 13:20 Массивы в сигналах/слотах
Цитата(urandom @ 13.12.2011, 22:46) *
Приветствую

Такой вот вопросик. Как можно через сигналы/слоты передать массив элементов с плавающей точкой (float)?
Советовали использовать QVector, но функция, которая отдает мне массив с QVector работать не может. А перекидывать все это из массива в QVector циклами как-то стремно (может есть другой вариант?). Да и медленно. Может объявить структуру с этим массивом и уже работать с ней? Будет ли это адекватным решением?
В общем нужно оптимальное и быстрое решение..


Я бы не стал использовать "голый" указатель, т.к. это чревато серьезными последствиями, если будет передача данных через очередь.
Использовал бы все-таки QVector или QByteArray.
Перевод массивов простых типов циклами - это, конечно, стрёмно, можно использовать memcpy();

float data[1024];
QVector< float > vec_data( sizeof( data ) / sizeof( float ) );
memcpy( vec_data.data(), data, sizeof( data ) );


float data[1024];
QByteArray vec_data( reinterpret_cast< char * >( data ), sizeof( data ) );


Если сигнал слот взаимодействие гарантировано только Qt::DirectConnection, то можно и указателем.
urandom,
7.11.2011, 13:52 QObject в QThread
Правильно так

MyThread::MyThread(QObject *parent) :
    QThread(parent)
{
}

MyThread::~MyThread()
{
    quit();
}

/// PROTECTED ///

void MyThread::run()
{
    MyObject myObject;
    connect(parent(), SIGNAL(mySignal(QString)), &myObject, SLOT(mySlot(QString)));
    // тут еще куча сигналов/слотов

    exec();
}


Нельзя просто так удалять объект MyObject в деструкторе, т.к. они сопоставлены разным потокам.
Ну и завершить поток нужно, чтобы не болтался.
urandom,
3.11.2011, 7:45 QMap + QThread
Цитата(AXELman4ever @ 3.11.2011, 0:13) *
То есть, если не лочить процесс изъятия элемента из карты, то вызванный метод ненароком может прочесть 1 элемента, а изъять совсем другой?

Верно абсолютно.

Цитата(AXELman4ever @ 3.11.2011, 0:13) *
А если элемент не извлекать вовсе, а только считывать его? Каким образом отсутствие мьютекса, в таком случае, может вызвать краш?


Предположим поток 1 записывает данные, а поток 2 считывает.
Запись данных приводит к вызову метода, внутри которого изменяются сами данные и структура их хранения.

Например, в реализации Qt для QMap сначала физически удаляются данные (вызывается деструктор), связанные с элементом, а затем правится структура QMap.

Так вот, без мьютекса, если метод чтения потока 2 будет вызван после удаления данных потоком 1, но до изменения структуры данных потоком 1, то это и может привести к крешу.
AXELman4ever,
3.11.2011, 7:29 QTableWidget and selected Rows
Можно используя

table->setCurrentCell ( row, column, QItemSelectionModel::Select );


либо

table->selectionModel()->select( index, QItemSelectionModel::Select );


Ну и разрешить мультивыбор нужно и сразу строки

table->setSelectionMode(QAbstractItemView::MultiSelection);
table->setSelectionBehavior( QAbstractItemView::SelectRows );

fortero,
2.11.2011, 17:17 QMap + QThread
Начиналось все с того, что

Цитата(AXELman4ever @ 27.10.2011, 13:21) *
1-ое:
Имеется 2 дочерних потока ("вытекающие" из мейн потока). Цель такова:

1 поток должен заносить значения в карту (QMap),
2 поток должен эти значения cчитывать.


Итак, если поток 2 должен иметь доступ к актуальным данным (даже на чтение), то без мьютексов не обойтись.

Цитата(AXELman4ever)
Но ведь (1) справедливо только для прямого вызова (используя Qt::DirectConnection), а если вести речь о вызове через сигнал/слот используя Qt::QueuedConnection?


Да все сработает, только нужно всегда помнить, что с сигналом tryToDoSmth() класса MyThread можно коннектится только как Qt::QueuedConnection. И обязательно указывать это в сопроводительной документации, если кто-то этим классом кроме Вас будет пользоваться. Просто не удобно.

Цитата(AXELman4ever)
Об очереди у меня сформировалось такое понятие - что каждый (не прямой) вызов метода из другого потока становится в очередь на выполнение в главном потоке. И когда главный поток берет на себя управление, он пересматривает очередь и выполняет в своем потоке все те задачи на выполнение, которые набежали от дочерних потоков.


Если соединение между сигналом и слотом выполнено с параметром Qt::QueuedConnection (в случае когда объекты связаны с разными потоками Qt::AutoConnection == Qt::QueuedConnection),

QObject::connect( obj1, SIGNAL( doFoo() ), obj2, SLOT( foo() ), Qt::QueuedConnection );

obj1 связан с thread1
obj2 связан с thread2

то при вызове сигнала doFoo() объекта obj1 формируется сообщение о необходимости вызова слота foo() у объекта obj2.
Это сообщение потоком thread1 помещается в очередь потока thread2. Когда thread2 доходит до обработки этого сообщения, тогда и вызывается слот foo().
Так что поняли, вроде, как правильно.

Просто ранее было написано, что к данным необходим доступ на чтение из дочернего потока.
AXELman4ever,
1.11.2011, 16:45 QMap + QThread
Цитата(AXELman4ever @ 1.11.2011, 14:33) *
"Метод объекта главного потока будет вызываться напрямую из дочернего потока", а выполняться он будет там же (в дочернем), или он оттуда будет только вызываться, а выполняться будет через очередь?


И выполняться он будет, там же, в дочернем потоке.
Где методы вызываются, там они и выполняются.

Очереди сообщений и реализованный через них механизм сигнал-слот взаимодействия - это все проделки Qt.

Цитата(AXELman4ever @ 1.11.2011, 14:33) *
А ведь сигнал принадлежит объекту, который в свою очередь принадлежит главному потоку


Сигналы и слоты - это обычные методы классов С++.
В С++ объекты не принадлежат никаким потокам.
Сопоставление QObject конкретному потоку реализовано непосредственно внутри Qt, но перехватывать вызов методов и перенаправлять их в очередь сообщений Qt не умеет.
Поэтому в каком потоке вызываем метод - в таком и выполняем (хоть сигнал, хоть слот, хоть обычный метод).

Цитата(AXELman4ever @ 1.11.2011, 14:33) *
А в чем заключается опасность?

Опасность в одновременном не синхронизированном доступе к данным из разных потоков, и как следствие возможном нарушения их целостности и крешу программы.
AXELman4ever,
1.11.2011, 8:46 QMap + QThread
В такой реализации скрыта серьезная ошибка.
Правда ее допускают вначале практически 95% программистов.

Объясняю:

Объект QThread - это класс "обертка" вокруг реального потока.
Как и любой объект QObject он принадлежит тому потоку, в котором он создан, в данном случае главному потоку.

Сигнал

emit tryToDoSmth();


в данном случае опасен, т.к. он принадлежит объекту из главного потока, а вызывается в дочернем.
Поэтому здесь Qt::AutoConnection == Qt::DirectConnection и метод объекта главного потока будет вызываться напрямую из дочернего потока.

Если написать явно Qt::QueuedConnection, то проблем быть не должно, тюк. метод будет вызываться через очередь.

Цитата
И вот как я понимаю это, есть доступ прямой - когда много потоков вызывают 1 метод не принадлежащий ему, и этот метод выполняет главный поток, и синхронный - когда выполнение метода переносится в другие потоки которые выполняют его синхронно по отношению друг к другу.


Методы не принадлежат потокам).

Прямой вызов - это непосредственный вызов слота, как-будто бы метод вызывается явно. Поэтому где он вызван, в том потоке он и выполняется.
Разные потоки всегда работают асинхронно, для их синхронизации и используются всякие приблуды типа мьютексов и семафоров.

Сделаю еще несколько замечаний:

1. Так писать не нужно, т.к. поток никогда корректно не завершиться.

void run()
{
   while(true){
       msleep(150);    
       emit tryToDoSmth();
   }
}


Нужно либо так

void run()
{
   while( not_stoped ){
       msleep(150);    
       emit tryToDoSmth();
   }
}

void setStopFlag ( bool yes )
{
    not_stoped = yes;
}


Либо так

void run()
{
    QTimer notifier; //  notifier принадлежит дочернему потоку, this принадлежит главному
    connect( &timer, SIGNAL( timeout() ), this, SIGNAL( tryToDoSmth() );
    notifier.start( 150 );
    exec();
}


2. В инициализации дочернего потока

MyThread *thread = new MyThread();


не указан родитель, т.о. thread никогда не удалиться (будут лики памяти)
Можно записать так

MyThread *thread = new MyThread( QCoreApplication::instance() );


3. Здесь очередь не запускается

thread->start();        //запускаем очередь потока


Очередь запускается только методом exec().
AXELman4ever,
31.10.2011, 13:53 QMap + QThread
Цитата(AXELman4ever @ 31.10.2011, 14:47) *
Так, понял. Но это в случае если метод, в котором осуществляется доступ к QMap будет выполнен в разных потоках. А вот когда оба потока вызовут метод на выполнение в главном потоке, а не каждый в своем, то ведь как не крути - очередь у главного потока одна, и все запросы на изменение объекта QMap буду выполнятся по-очередно, ведь так?


Нет, не так.
Вызов методов QMap прямой и синхронный и каждый в своем потоке, а не через очередь сообщений.

Цитата(AXELman4ever @ 31.10.2011, 14:47) *
оба потока вызовут метод на выполнение в главном потоке, а не каждый в своем


А это как возможно? Если только главный поток содержит некий диспетчер для QMap.))

Цитата(AXELman4ever @ 31.10.2011, 14:47) *
К примеру, 2 потока отправляют сигнал с параметрами на слот главного потока.


Тогда QMap не является общими данными для разных потоков, а является данными для главного потока.
Смотря как нужно для реализации.

Пусть изменения можно внести и так, а как быть с получением данных от QMap??? Или данные QMap в разных потоках не нужны, тогда зачем вообще городить огород с потоками, когда можно все реализовать в главном потоке???
AXELman4ever,
31.10.2011, 9:31 Как узнать какую модель отображает представление в данный момент?
Цитата(Флинт @ 31.10.2011, 10:19) *
Метод model() у представления возвращает указатель типа QAbstractItemModel, а что с ним делать дальше? Что-то я запутался.


Можно так

if ( QByteArray( model()->metaObject()->className() ) == QByteArray( "MyModel" ) )
{
    // моя модель
}


или так

if ( model()->metaObject() == &MyModel::staticMetaObject )
{
    // моя модель
}


Главное не забыть определить макрос Q_OBJECT в классе MyModel.
Флинт,

2 страниц V   1 2 >
RSS Текстовая версия Сейчас: 22.11.2024, 2:01