crossplatform.ru

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

10 страниц V  « < 6 7 8 9 10 >  
Ответить в данную темуНачать новую тему
> Секреты и интересные возможности Qt
SABROG
  опции профиля:
сообщение 24.4.2010, 15:44
Сообщение #71


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Администратор это объяснил так:

Цитата
Все блоги, которые давно не обновлялись, и те, что использовались только для SEO были удалены.


Для SEO я блог не использовал. Обновлялся он конечно не часто, но это не повод удалять полезную информацию у которой нет срока давности.

Сообщение отредактировал SABROG - 24.4.2010, 15:45
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 26.5.2010, 17:27
Сообщение #72


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


На заметку:

Заполняем Qt контейнер без for:
#include <algorithm>

#include <QtCore/QtGlobal>
#include <QtCore/QtDebug>
#include <QtCore/QList>

struct inc_functor
{
    inc_functor() : counter(0) {}
    inline int operator()() {return counter++;}
    int counter;
};

int main(int argc, char** argv)
{
    QList<int> testList;
    std::generate_n(std::back_insert_iterator<QList<int> >(testList),
                10, inc_functor());
    qDebug() << testList;
    return 0;
}


(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)


Ищем элемент контейнера удовлетворяющий нашим требованиям без for используя предикат:

// поиск первого неактивного (Disabled) виджета через аттрибуты
struct testAttributePredicate {
    testAttributePredicate(Qt::WidgetAttribute attrib) : m_attrib(attrib) {}
    inline bool operator()(QWidget* widget) {
        return widget->testAttribute(m_attrib);
    }
    Qt::WidgetAttribute m_attrib;
};
...
{
    QWidgetList widgets = qApp->allWidgets();
    QWidgetList::iterator result =
            std::find_if(widgets.begin(), widgets.end(),
                         testAttributePredicate(Qt::WA_Disabled));
    if (result != widgets.end())
        qDebug() << (*result)->objectName();
}


Передача указателя на метод класса для QtConcurrent::mapped() вместо обычной функции:

#include <QtConcurrentMap>
#include <functional>
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QVector<int> test;
    test << 1 << 2 << 3;

    QtConcurrent::mapped(test, std::bind1st(std::mem_fun(&MainWindow::myMethod), this));
}

int MainWindow::myMethod(int i)
{
    qDebug() << i;
    return i;
}


Сообщение отредактировал SABROG - 26.5.2010, 20:17
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 26.5.2010, 19:17
Сообщение #73


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


а зачем в
struct testAttributePredicate
оператор operator()(QWidget* widget) ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 26.5.2010, 20:13
Сообщение #74


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(Litkevich Yuriy @ 26.5.2010, 20:17) *
а зачем в
struct testAttributePredicate
оператор operator()(QWidget* widget) ?


Так это обычный функтор, в функции find_if я создаю объект, передавая в конструктор параметр (аттрибут), который нужно искать, а стандартная библиотека в своем шаблоне осуществляет вызов уже через перегруженный оператор:

// приблизительное поведение (не исходный код шаблона find_if)
template<class InputIterator, class testAttributePredicate>
  InputIterator find_if ( InputIterator first, InputIterator last, testAttributePredicate obj)
  {
    for (; first!=last; first++ ) if ( obj(*first) ) break;
// obj(*first) - вызывается перегруженный оператор (). То есть функция заранее ожидает, что я его перегружу.
    return first;
  }
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 21.6.2010, 18:23
Сообщение #75


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Реализовал установку приоритета потока в параллельном программировании.

Как многие заметили в Qt есть метод QThread::setPriority(), а вот как задать приоритет потоку запущенному например через QtConcurrent::run() не понятно. В новом стандарте C++0x будет метод std::call_once, который является потокобезопасной функций для выполнения определеннной функции один лишь раз. Аналогичная функция есть и в BOOST'e. Посмотрев на код функции я пришел к выводу, что проще переписать её на Qt, чем заставлять людей тащить с собой BOOST. С другой стороны моя реализация получилась в 2 раза быстрей BOOST'овской, но медленней std::call_once. Связано это со скудными возможностями класса QAtomicInt, там где я бы мог обойтись быстрыми атомарными операциями загрузки (load) и сохранения (store), мне пришлось импровизировать и использовать более медленные атомарные методы (fetchAndStoreAcquire, fetchAndStoreRelease).

call_once.h

#ifndef CALL_ONCE_H
#define CALL_ONCE_H

#include <QtCore/QtGlobal>
#include <QtCore/QAtomicInt>
#include <QtCore/QMutex>
#include <QtCore/QWaitCondition>
#include <QtCore/QThreadStorage>
#include <QtCore/QThread>

namespace CallOnce {
    enum ECallOnce {
        CO_Request,
        CO_InProgress,
        CO_Finished
    };

    Q_GLOBAL_STATIC(QThreadStorage<QAtomicInt*>, once_flag)
}

template <class Function>
        inline static void qCallOnce(Function func, QBasicAtomicInt& flag)
{
    using namespace CallOnce;
    int protectFlag = flag.fetchAndStoreAcquire((int)flag);
    if (protectFlag == CO_Finished)
        return;
    if (protectFlag == CO_Request && flag.testAndSetRelaxed(protectFlag,
                                                            CO_InProgress)) {
        func();
        flag.fetchAndStoreRelease(CO_Finished);
    }
    else {
        do {
            QThread::yieldCurrentThread();
        }
        while (!flag.testAndSetAcquire(CO_Finished, CO_Finished));
    }
}

template <class Function>
        inline static void qCallOncePerThread(Function func)
{
    using namespace CallOnce;
    if (!once_flag()->hasLocalData()) {
        once_flag()->setLocalData(new QAtomicInt(CallOnce::CO_Request));
        qCallOnce(func, *once_flag()->localData());
    }
}

#endif // CALL_ONCE_H

call_once_test.cpp
#include <QtCore/QtGlobal>
#include <QtCore/QtDebug>

#include <QtCore/QTimer>

#include <QtCore/QTime>

#include <QtCore/QVector>
#include <QtCore/QThread>
#include <QtCore/QtConcurrentMap>
#include <QtCore/QtConcurrentFilter>
#include <QtCore/QCoreApplication>

#include <algorithm>

#include "call_once.h"

enum {Max = 100};

struct run_once
{
    void operator()()
    {
        qDebug() << "Functor: This only once...";
    }
};

void func_run_once()
{
    qDebug() << "Function: This only once...";
}

struct inc_functor
{
    inc_functor() : counter(0) {}
    inline int operator()() {return counter++;}
    int counter;
};

struct setPriorityFunctor
{
    setPriorityFunctor(QThread::Priority priority = QThread::NormalPriority)
        : m_priority(priority) {}
    inline void operator()()
    {
        QThread* thread = QThread::currentThread();
        thread->setPriority(m_priority);
    }
    QThread::Priority m_priority;
};

void setLowestPriorityFunction()
{
    QThread* thread = QThread::currentThread();
    thread->setPriority(QThread::LowestPriority);

    qDebug("Current thread %x. Thread set to Lowest priority",
           (quintptr)thread);
}

void setHighestPriorityFunction()
{
    QThread* thread = QThread::currentThread();
    thread->setPriority(QThread::HighestPriority);

    qDebug("Current thread %x. Thread set to Highest priority",
           (quintptr)thread);
}

int calculate(const int& num)
{
#if 0 // Test once call per thread with function
    #if 0 // Set lowest thread priority
        qCallOncePerThread(setLowestPriorityFunction);
    #else // Set highest thread priority
        qCallOncePerThread(setHighestPriorityFunction);
    #endif
#else // Test once call per thread with functor
    #if 0
        qCallOncePerThread(setPriorityFunctor(QThread::HighestPriority));
    #else
        qCallOncePerThread(setPriorityFunctor(QThread::LowestPriority));
    #endif
#endif

    return ~num;
}

static QBasicAtomicInt flag = Q_BASIC_ATOMIC_INITIALIZER(CallOnce::CO_Request);

int parityFilter(const int& num)
{
    qCallOnce(run_once(), flag);

    return num % 2 ? false : true;
}

static QBasicAtomicInt testflag = Q_BASIC_ATOMIC_INITIALIZER(CallOnce::CO_Request);

int main(int argc, char* argv[])
{
    QCoreApplication a(argc, argv);

    QTime t; t.start();
    for (int i = 0; i < 1000 * 1000 * 100; ++i)
        qCallOnce(run_once(), testflag);
    qDebug("%d ms", t.elapsed());

    QVector<int> ints;

    std::generate_n(std::back_insert_iterator<QVector<int> >(ints),
                                                (int)Max, inc_functor());

// Test qCallOnce
    {
        QVector<int> results = QtConcurrent::blockingMapped(ints, calculate);
        qDebug() << results;
    }

// Test qCallOncePerThread
    {
        QtConcurrent::blockingFilter(ints, parityFilter);
        qDebug() << ints;
    }

    return 0;
}


P.S.: функция также может пригодится для создания потоко-безопасных синглтонов.
Прикрепленные файлы
Прикрепленный файл  call_once.tar.gz ( 1,62 килобайт ) Кол-во скачиваний: 1012
 
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
kuzulis
  опции профиля:
сообщение 21.6.2010, 18:54
Сообщение #76


Активный участник
***

Группа: Участник
Сообщений: 393
Регистрация: 29.6.2009
Пользователь №: 862

Спасибо сказали: 36 раз(а)




Репутация:   7  


SABROG, а с Троллями (нокией) пробовали это обсудить? Мож они включат это в свой код?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 22.6.2010, 11:19
Сообщение #77


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Цитата(kuzulis @ 21.6.2010, 19:54) *
SABROG, а с Троллями (нокией) пробовали это обсудить? Мож они включат это в свой код?

Если руки дойдут попробую сделать commit request для git'a.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 23.6.2010, 14:52
Сообщение #78


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


В старом проекте на Borland Builder C++ у меня были кнопочки со стилем csFramed. Захотелось узнать возможно ли такие сделать в Qt. Нашел флаг для свойства border в qss - groove, но как выяснислось в нем нельзя задать контрастные цвета например черный и белый. То есть задать можно один цвет на основе которого вычисляется второй. Цвета типа черный или белый не подходят, создается просто черный бордюр. Пришлось написать собственную версию:



qss

QPushButton {
/*top right bottom left (clockwise)*/
background-color: #d6d3ce;
border-width: 2px 3px 3px 2px;
border-style: solid;
border-color:
qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 white, stop:0.5 white, stop:0.51 #848284, stop:1 #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:0, y2:1, stop:0 white, stop:0.33 white, stop:0.34 black, stop:0.67 black, stop:0.68 #848284, stop:1.0  #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 white, stop:0.33 white, stop:0.34 black, stop:0.67 black, stop:0.68 #848284, stop:1.0 #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:0, y2:1, stop:0 white, stop:0.5 white, stop:0.51 #848284, stop:1 #848284);
}

QPushButton:default{
border-width: 3px 4px 4px 3px;
border-color:
qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 white, stop:0.33 white, stop:0.34 black, stop:0.67 black, stop:0.68 #848284, stop:1.0 #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:0, y2:1, stop:0 white, stop:0.25 white, stop:0.26 black, stop:0.50 black, stop:0.51 black, stop:0.75 black, stop:0.76 #848284, stop:1 #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 white, stop:0.25 white, stop:0.26 black, stop:0.50 black, stop:0.51 black, stop:0.75 black, stop:0.76 #848284, stop:1 #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:0, y2:1, stop:0 white, stop:0.33 white, stop:0.34 black, stop:0.67 black, stop:0.68 #848284, stop:1.0  #848284);
}

QPushButton:pressed{
border-width: 3px;
border-color:
qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 #848284, stop:0.33 #848284, stop:0.34 black, stop:0.67 black, stop:0.68 #848284, stop:1.0 #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:0, y2:1, stop:0 white, stop:0.33 white, stop:0.34 black, stop:0.67 black, stop:0.68 #848284, stop:1.0  #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 white, stop:0.33 white, stop:0.34 black, stop:0.67 black, stop:0.68 #848284, stop:1.0 #848284)
qlineargradient(spread:pad, x1:1, y1:1, x2:0, y2:1, stop:0 #848284, stop:0.33 #848284, stop:0.34 black, stop:0.67 black, stop:0.68 #848284, stop:1.0  #848284);
}



Сообщение отредактировал SABROG - 23.6.2010, 18:11
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
SABROG
  опции профиля:
сообщение 25.6.2010, 11:57
Сообщение #79


Профессионал
*****

Группа: Участник
Сообщений: 1207
Регистрация: 8.12.2008
Из: Russia, Moscow
Пользователь №: 446

Спасибо сказали: 229 раз(а)




Репутация:   34  


Продолжил издеваться над кнопками и qss:



qss

QPushButton {
font-weight: bold;
border: 1px solid black;
border-radius: 7px;
color: white;
background-color:
qradialgradient(spread:pad, cx:0.51, cy:-1.0, radius:2, fx:0.50, fy:0.0, stop:0.53 #81beff, stop:0.54 #268fff, stop:1 #268fff);
}

QPushButton:hover {
color: qlineargradient(spread:pad, x1:1, y1:1, x2:1, y2:0, stop:0 black, stop:0.5 white);
}

QPushButton:pressed {
padding: 3px 0px 0px 3px;
background-color:
qradialgradient(spread:pad, cx:0.51, cy:-1.0, radius:2, fx:0.50, fy:0.0, stop:0.51 #0061ff, stop:0.52 #268fff, stop:1 #268fff);
}

QPushButton:default {
border-width: 2px;
}

QPushButton:focus {
border: 4px double black;
}

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 1.8.2010, 11:53
Сообщение #80


фрилансер
******

Группа: Участник
Сообщений: 2941
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


Обнаружил любопытный спецэффект: если в качестве подменю (QMenu) задать элементу другое предыдущее по иерархии меню, то при выборе пункта все предыдущие подменю изчезают с экрана и показывается указанное ))

К примеру:

----------------
m1
----------------
A1 > (m2)
A2
A3
----------------



отделено от темы "Создание вложенного действия QAction"

----------------
m2
----------------
A4
A5 > (m1)
A6
----------------

Выбор пунктов A1>A5 покажет на экране опять таки меню m1


---------------------------------------------------
Уточнил - не всё так радужно.


    #include <QMenu>

    QMap<QString,QAction*> map;
    const char* text=0;


    //менюшка первого уровня
    QMenu& m1=*new QMenu(this);
        text="11";        map[text]=m1.addAction(text);
        text="12";        map[text]=m1.addAction(text);
        text="13";        map[text]=m1.addAction(text);
        
    //менюшка второго уровня
    QMenu& m2=*new QMenu(this);
        text="21";        map[text]=m2.addAction(text);
        text="22";        map[text]=m2.addAction(text);
        text="23";        map[text]=m2.addAction(text);
        
    //менюшки третьего уровня
    QMenu& m3_1=*new QMenu(this);
        text="311";        map[text]=m3_1.addAction(text);
        text="312";        map[text]=m3_1.addAction(text);
        text="313";        map[text]=m3_1.addAction(text);
        text="314";        map[text]=m3_1.addAction(text);
    QMenu& m3_2=*new QMenu(this);
        text="321";        map[text]=m3_2.addAction(text);
        text="322";        map[text]=m3_2.addAction(text);
        text="323";        map[text]=m3_2.addAction(text);
    QMenu& m3_3=*new QMenu(this);
        text="331";        map[text]=m3_3.addAction(text);
        text="332";        map[text]=m3_3.addAction(text);
        text="333";        map[text]=m3_3.addAction(text);


    //связываем вложенные меню
    map["12"]->setMenu(&m2);

    map["21"]->setMenu(&m3_1);
    map["22"]->setMenu(&m3_2);
    map["23"]->setMenu(&m3_3);

    map["311"]->setMenu(&m1);
    map["311"]->setText("open m1");//откроется меню первого уровня
    
    map["312"]->setMenu(&m2);
    map["312"]->setText("open m2");//ничего не произойдёт
    
    map["313"]->setMenu(&m3_1);
    map["313"]->setText("open m3_1");//ничего не произойдёт, только подсветка прыгнет наверх
    
    map["314"]->setMenu(&m3_2);
    map["314"]->setText("open m3_2");//откроется ещё один уровень вложенности (стандартное поведение)

    //отображаем меню    
    m1.popup(cursor().pos());


1) если в в любом вложенном меню указать меню первого уровня в качестве вложенного далее, то выбор этого пункта закроет все подменю и покажет только меню первого уровня

2) если так же указать одно из промежуточных подменю, то ничего не произойдёт

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

4) если так же указать не учавствовавшее в цепочке подменю, оно просто откроется как вложенное

Сообщение отредактировал Алексей1153 - 1.8.2010, 18:48
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

10 страниц V  « < 6 7 8 9 10 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


4 чел. читают эту тему (гостей: 4, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 23.11.2024, 4:14