redakcją
Sorry chłopaki, mam bardzo ciężko łączącą „kolejce” Typ niestandardowy Przykład z wymaganiami.
O ile mogę stwierdzić na podstawie pytania, po zaakceptowaniu lub odrzuceniu obrazu przez użytkownika musi on być opcjonalnie obrócony i/lub skalowany i zawsze zapisywany w określonym katalogu i przechodzić do następnego obrazu. (-> brak interakcji z użytkownikiem)
Nawet jeśli użytkownik opuści bieżące okno dialogowe, zdjęcie nadal musi zostać zapisane.
Przykład "Queued Custom Type" obsługuje tylko jeden obraz, jest zawsze połączony z gui, a gdy użytkownik opuszcza okno dialogowe, operacja wątku jest zatrzymana.
Tak więc jeśli uruchamia swój program z przykładu Queue, prawdopodobnie zacznie pisać kolejkę obrazów chronionych muteksem, aby mógł dodawać nowe obrazy do listy, jeśli są oczekujące operacje zapisu. W przeciwnym razie użytkownik nadal musi czekać na operacje oczekujące.
Drugi problem polega na tym, że prawdopodobnie nie chce czekać na oczekujące operacje składowania po zamknięciu okna dialogowego.
Co zrobić, aby spełnić wymagania, działa z pulą wątków. Nakarm pulę wątków w wybrane operacje składowania i użyj wzoru dekoratora opartego na QRunnable, jeśli trzeba go również obrócić/przeskalować. Całe kolejkowanie jest obsługiwane poprawnie przez bibliotekę, a oczekujące operacje są wykonywane, nawet jeśli użytkownik opuści bieżące okno dialogowe. Na koniec prawdopodobnie użyłbym kolejkowego kodu przykładowego, aby załadować nowe obrazy i dać użytkownikowi wskazanie oczekiwania na operację ładowania.
Moje runnable i dekorator prawdopodobnie wyglądałyby tak ... (może niektóre dodatkowe konstruktory, które zastąpiłyby ustawione funkcje), więc mogę bardzo łatwo dodać nową operację, taką jak ta QThreadPool::globalInstance()->start(saver);
, bez użycia jakiegokolwiek obiektu synchronizacji niskiego poziomu.
class ImageDecorator : public QRunnable
{
NextStep nextStep;
public:
typedef boost::shared_ptr<QRunnable> NextStep;
ImageDecorator(const NextStep& nextStep) : nextStep(nextStep) {
}
ImageDecorator() : nextStep() {
}
// set/get image functions....
protected:
void next() {
if(nextStep)
nextStep->run();
}
};
class RotateImage : public ImageDecorator
{
public:
typedef boost::shared_ptr<Image> Image;
RotateImage(const NextStep& nextStep) : ImageDecorator(nextStep) {
}
RotateImage() : ImageDecorator() {
}
// set angle functions....
private:
void run()
{
// rotate the image
// ...
next();
}
};
class ResizeImage : public ImageDecorator
{
public:
typedef boost::shared_ptr<Image> Image;
ResizeImage(const NextStep& nextStep) : ImageDecorator(nextStep) {
}
ResizeImage() : ImageDecorator() {
}
// set size functions....
private:
void run()
{
// resize the image
next();
}
};
class SaveImage : public ImageDecorator
{
public:
typedef boost::shared_ptr<Image> Image;
SaveImage(const NextStep& nextStep) : ImageDecorator(nextStep) {
}
SaveImage() : ImageDecorator() {
}
// set fileName functions....
private:
void run()
{
// save the image
next();
}
};
// save the image
SaveImage *const saver(new SaveImage());
saver->setImage(/*use shared pointer*/);
saver->setFilename(...);
QThreadPool::globalInstance()->start(saver);
// rotate and save the image
const ImageDecorator::NextStep saver(new SaveImage());
saver->setImage(/*use shared pointer*/);
saver->setFilename(...);
RotateImage *const rotateAndSave(new RotateImage(saver));
rotateAndSave->setImage(/*use shared pointer*/);
rotateAndSave->setAngle(...);
QThreadPool::globalInstance()->start(rotateAndSave);
// resize rotate and save the image
const ImageDecorator::NextStep saver(new SaveImage());
saver->setImage(/*use shared pointer*/);
saver->setFilename(...);
const ImageDecorator::NextStep rotateAndSave(new RotateImage(saver));
rotateAndSave->setImage(/*use shared pointer*/);
rotateAndSave->setAngle(...);
ResizeImage *const resizeRotateAndSave(new ResizeImage(rotateAndSave));
resizeRotateAndSave->setImage(/*use shared pointer*/);
resizeRotateAndSave->setSize(...);
QThreadPool::globalInstance()->start(resizeRotateAndSave);
Jedno słowo ostrzeżenia. Nie można używać QPixmaps poza wątkiem GUI. Ostatnio zostałem ukąszony przez to, że jest to podobna aplikacja do renderowania obrazów gwintowanych. Zamiast tego użyj QImage. Jeśli naprawdę potrzebujesz QPixmap (co zrobiłem), będziesz musiał zwrócić QImage z wątku i wykonać konwersję (która jest dość droga) w głównym wątku GUI. –