Wywoływanie slotu w C++ z QML.

Moje eksperymenty z QtQuick2 spowodowały, że całkowicie zmieniłem zdanie na temat Qt5 i muszę przyznać, że minę mam coraz częściej taką 8-O.

cppslotfromqml
Po przemyśleniu możliwości model-view-controller, gdzie widok generowany jest z QML przez OpenGL, a dynamiczne z natury dzisiejszych urządzeń zmiany interfejsu zakodowane są w EcmaScript (JS) osadzonym w QML, oprócz tego łatwość wywoływania funkcji w C++ i Javie, dochodzę do wniosku, że Qt5 rządzi ;).

Hello World w QtQuick2.

QtQuick jest fascynujące:

Animacje to nawet nie kilka linijek kodu… a za ich wyświetlanie odpowiada OpenGL lub OpenGL ES 2.0.

QtQuick może być też osadzone w klasycznym oknie QWindow:

qmlAle póki co, nadal w Qt-5.5.1 nie działa to na Androidzie (QtQuick i QWidgets to dwie osobne powierzchnie wyświetlania w OpenGL, na Antku nie jest to póki co obsługiwane i może być albo QtQuick albo QWidgets).


ui->setupUi(this);

QQuickView *view = new QQuickView;
QWidget *container = QWidget::createWindowContainer(view, this);
view->setSource(QUrl::fromLocalFile("main.qml"));

ui->verticalLayout->addWidget(container);

OptionsDialog.

TreeView na Androidzie sprawdza się średnio, zastanawiałem się jak to można by zrobić w Qt5 i przyznam szczerze, łatwo nie jest. QScrollView ma jedną podstawową wadę: póki co nie obsługuje przewijania jednym palcem i trzeba mu zostawić włączony scrollbar, na szczęście udało się go poprawić za pomocą stylów:

O kwestię layoutów mam ochotę zapytać któregoś z developerów, bo niestety są bardzo nieprzewidywalne. Nigdy nie wiadomo gdzie i jak dany widget się wyświetli. Na powyższym zrzucie odległości między obiektami są różne, a powinny być względnie spójne, bo na samym dole kontenera dodałem expander, który powinien wszystko co powyżej niego ładnie do siebie dosunąć…

Mam nadzieję, że kiedyś pojawi się spójne scrollview z obsługą single finger pan. Póki co się nie zanosi. A przecież aplikacji w QtWidgets jest niewspółmiernie więcej na wolności, niż w QtQuick.

AspeQt na Kazam Tornado 348.

A oto żywy dowód na prawidłową obsługę usb-host przez Kazam Tornado:

Przy okazji powiększyłem trochę przyciski i jeśli ekran jest mniejszy od 5″ to log jest wyłączony (wyświetla się na pasku statusu), a hbox-y wypełniają cały ekran:

Screenshot_2015-09-06-02-59-05Z małych ważnych zmian: usunąłem orientację poziomą i dzięki temu można sobie wybrać plik do załadowania w Fileselektorze w pionie (więcej się mieści).

scr-orient

 

AspeQt dla Windows.

Piętnaście emulowanych napędów w AspeQt to było dla mnie zdecydowanie za dużo 🙂 więc „zandroidyzowałem” plik projektu z repo dla Androida i wydzieliłem co androidowe, dzięki czemu mój fork AspeQt dla Antka kompiluje się też pod Windows i pod Linuksem. Obsługa portu odbywa się wtedy przez standardowy moduł serialport-{win32,linux}.cpp. Przy okazji poprawiłem kodowanie znaków, które w AspeQt pod Windows było skopane od dawna:

AspeQt_WindowsBinarka dla Windows z wymaganymi bibliotekami tutaj.

winandroidlinux

Qt5 – Natywny file&directory selector przez JNI.

QFileDialog w Qt5 na Androidzie jest fatalny. Na szczęście znalazłem minimalistyczny fileselector:

http://www.scorchworks.com/Blog/simple-file-dialog-for-android-applications/

który świetnie się sprawdza w AspeQT:

IMG_20150719_123904Musiałem go tylko lekko zmodyfikować, bo na nazwę pliku oczekuję w pętli po stronie Qt (lame, ale brakło mi czasu na bardziej eleganckie rozwiązanie)  i bez Cancel nie dało się z niej wyskoczyć:

QAndroidJniObject::callStaticMethod<void>("net/greblus/MyActivity", "runFileChooser", "()V");

QString fileName = NULL;
do
{
   QAndroidJniObject jFileName = QAndroidJniObject::getStaticObjectField<jstring>("net/greblus/MyActivity", "m_chosen");
   fileName = jFileName.toString();

   if (fileName == "Cancelled") {fileName.clear(); break;}
   if (fileName == "None") QThread::yieldCurrentThread();
}
while (fileName == "None");

A w Javie, cały widz polega na tym, że MyActivity jest singletonem i niestatyczne metody (jak w FileChooser) trzeba wołać w wątku UI Androida z instancji singletona:


public class MyActivity extends QtActivity
{
   ...
   public static MyActivity s_activity = null;
   ...
   public void onCreate(Bundle savedInstanceState)
   {
      s_activity = this;
   }
   ...
}
public static void runFileChooser() {
   m_chosen = "None";
   MyActivity.s_activity.runOnUiThread( new FileChooser() );
}

i wtedy można z C++ wywołać QAndroidJNIObject tak:

QAndroidJniObject::callStaticMethod<void>("net/greblus/MyActivity", "runFileChooser", "()V");

Lekko zmodyfikowany plik tutaj.

bigger_aspeqt