tBane Temat założony przez niniejszego użytkownika |
» 2024-10-01 17:15:53 Ok. Dodałem długość scroll'a - scrollLength i poprawiłem równania: sf::Vector2f scrollPosition; scrollPosition.x = position.x + size.x / 4.0f; scrollPosition.y = position.y + scrollLength * size.x / 4.0f +( scrollValue - minValue ) /( maxValue - scrollLength + 1 - minValue ) *( size.y - scrollLength * size.x / 2.0f ); scroll.setPosition( scrollPosition );
if( event.type == sf::Event::MouseMoved ) { if( pressed ) { sf::Vector2f mousePos = window->mapPixelToCoords( sf::Vector2i( event.mouseMove.x, event.mouseMove.y ) ); if( fabs( mousePos.x - mouseStartPos.x ) > 100 ) mousePos = mouseStartPos; float value =( mousePos.y + mouseOffset.y - position.y ) /( size.y ) *( maxValue - minValue ) + minValue; if( value < minValue ) value = minValue; else if( value > maxValue - scrollLength + 1 ) value = maxValue - scrollLength + 1; scrollValue = value; } }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-01 18:14:56 Jeszcze potrzebuję zrobić tak, by kursor był zawsze na środku scrolla podczas scrollowania, bo obecnie jest na jego początku. Domyślam się, że powinienem edytować wartość: scroll = sf::RectangleShape( sf::Vector2f( size.x, scrollLength * size.x / 2.0f ) ); scroll.setOrigin( 0, scrollLength * size.x / 2.0f ); scroll.setFillColor( sf::Color::Red );
sf::Vector2f scrollPosition; scrollPosition.x = position.x; scrollPosition.y = position.y + scrollLength * size.x / 2.0f; scrollPosition.y +=( scrollValue - minValue ) /( maxValue - scrollLength + 1 - minValue ) *( size.y - scrollLength * size.x / 2.0f ); scroll.setPosition( scrollPosition );
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-01 20:08:24 Ok udało się :-) Raczej dam radę sam resztę zaprogramować. // edit Nie udało się, ale przynajmniej jako tako scrollPosition.y = position.y +( scrollValue - minValue ) /( maxValue - minValue ) *( size.y - scrollLength * size.x / 2.0f );
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-01 21:04:51 Opakowałem kod Dialog Box'a w klasę. Teraz zastanawiam się jak zrobić tak, żeby można było zarówno wchodzić w katalogi jak i cofać się. Text Area:#ifndef TextArea_hpp #define TextArea_hpp
class TextArea { public: string s; sf::Vector2f position; sf::Text text; sf::RectangleShape rect; TextArea( string s ) { this->s = s; text = sf::Text(); text.setFont( basicFont ); text.setCharacterSize( 16 ); text.setString( s ); sf::Vector2f textPos; textPos.x = position.x + float( text.getCharacterSize() ) * 0.2f; textPos.y = position.y; text.setPosition( textPos ); sf::Vector2f size; size.x = float( text.getLocalBounds().getSize().x ) * 1.05f; size.y = float( text.getCharacterSize() ) * 1.3f; rect.setSize( size ); } void setRectSize( sf::Vector2f size ) { rect.setSize( size ); } void setString( string s ) { this->s = s; text.setString( s ); } void setPosition( sf::Vector2f position ) { this->position = position; rect.setPosition( position ); sf::Vector2f textPos; textPos.x = position.x + float( text.getCharacterSize() ) * 0.2f; textPos.y = position.y; text.setPosition( textPos ); } void setCharacterSize( short val ) { text.setCharacterSize( val ); sf::Vector2f size; size.x = float( text.getLocalBounds().getSize().x ) * 1.05f; size.y = float( text.getCharacterSize() ) * 1.3f; rect.setSize( size ); } void setRectColor( sf::Color color ) { rect.setFillColor( color ); } void setTextColor( sf::Color color ) { text.setFillColor( color ); } sf::Vector2f getSize() { return rect.getSize(); } void update( float dt ) { } void draw() { window->draw( rect ); window->draw( text ); } };
#endif
Scrollbar:#ifndef Scrollbar_hpp #define Scrollbar_hpp
class Scrollbar { public: sf::Vector2f size; sf::Vector2f position; float minValue; float maxValue; float scrollValue; float scrollLength; sf::RectangleShape bar; sf::RectangleShape scroll; bool pressed; sf::Vector2f mouseStartPos; sf::Vector2f mouseOffset; Scrollbar( sf::Vector2f size, sf::Vector2f position, float minValue, float maxValue, float scrollValue, float scrollLength ) { this->size = size; this->position = position; this->minValue = minValue; this->maxValue = maxValue; this->scrollValue = scrollValue; this->scrollLength = scrollLength; bar = sf::RectangleShape( size ); bar.setFillColor( sf::Color::Blue ); scroll = sf::RectangleShape( sf::Vector2f( size.x, scrollLength * size.x ) ); scroll.setOrigin( 0, 0 ); scroll.setFillColor( sf::Color::Red ); pressed = false; } void setValue( int value ) { scrollValue = value; if( scrollValue > maxValue - scrollLength + 1 ) scrollValue = maxValue - scrollLength + 1; if( scrollValue < minValue ) scrollValue = minValue; } void update( sf::Event & event ) { bar.setPosition( position ); sf::Vector2f scrollPosition; scrollPosition.x = position.x; scrollPosition.y = position.y +( scrollValue - minValue ) /( maxValue - minValue ) *( size.y - scrollLength / 2.0f * size.x ); scroll.setPosition( scrollPosition ); if( event.type == sf::Event::MouseButtonPressed ) { if( event.mouseButton.button == sf::Mouse::Left ) { sf::Vector2f mousePos = window->mapPixelToCoords( sf::Vector2i( event.mouseButton.x, event.mouseButton.y ) ); if( scroll.getGlobalBounds().contains( worldMousePosition ) ) { pressed = true; mouseStartPos = mousePos; mouseOffset = scrollPosition - mousePos; } } } if( event.type == sf::Event::MouseButtonReleased ) { if( event.mouseButton.button == sf::Mouse::Left ) { pressed = false; } } if( event.type == sf::Event::MouseMoved ) { if( pressed ) { sf::Vector2f mousePos = window->mapPixelToCoords( sf::Vector2i( event.mouseMove.x, event.mouseMove.y ) ); if( fabs( mousePos.x - mouseStartPos.x ) > 100 ) mousePos = mouseStartPos; float value =( mousePos.y + mouseOffset.y - position.y ) /( size.y ) *( maxValue - minValue ) + minValue; setValue( value ); } } } void draw() { window->draw( bar ); window->draw( scroll ); } };
#endif
Open Dialog Box:#ifndef OpenDialogBox_hpp #define OpenDialogBox_hpp
bool sortkey( std::filesystem::directory_entry first, std::filesystem::directory_entry second ) { if( first.path().extension() < second.path().extension() ) { return true; } return false; }
class OpenDialogBox { public: sf::Vector2f position = sf::Vector2f( 300, 300 ); sf::RectangleShape rect; sf::RectangleShape titlebar; TextArea * title; sf::RectangleShape submitbar; TextArea * filename; TextArea * selectedFilename; TextButton * submitButton; std::string folderPath = "assets"; sf::RectangleShape textField[ 8 ]; std::vector < std::filesystem::directory_entry > paths; TextArea * texts[ 7 ]; sf::Sprite icons[ 7 ]; Scrollbar * scrollbar; OpenDialogBox() { rect = sf::RectangleShape( sf::Vector2f( 512, 256 + 32 ) ); rect.setFillColor( sf::Color( 64, 64, 64 ) ); rect.setPosition( position.x - 256, position.y - 128 - 32 ); titlebar = sf::RectangleShape( sf::Vector2f( 512, 32 ) ); titlebar.setFillColor( sf::Color( 48, 48, 48 ) ); titlebar.setPosition( position.x - 256, position.y - 128 - 32 ); title = new TextArea( "Dialog box" ); title->setCharacterSize( 24 ); title->setPosition( sf::Vector2f( position.x - 256 + 8, position.y - 128 - 32 ) ); title->setRectColor( sf::Color::Transparent ); title->setTextColor( textColor ); paths.clear(); if( filesystem::exists( folderPath ) && filesystem::is_directory( folderPath ) ) { for( auto & entry: filesystem::directory_iterator( folderPath ) ) { paths.push_back( entry ); } } std::sort( paths.begin(), paths.end(), sortkey ); sf::Vector2f scrollbarSize = sf::Vector2f( 16, 256 - 32 ); sf::Vector2f scrollbarPosition = sf::Vector2f( position.x + 256 - scrollbarSize.x, position.y - 128 ); scrollbar = new Scrollbar( scrollbarSize, scrollbarPosition, 0, paths.size() - 1, 0, 7 ); for( int i = 0; i < 7; i++ ) { textField[ i ] = sf::RectangleShape( sf::Vector2f( 512, 32 ) ); textField[ i ].setFillColor( sf::Color::Transparent ); textField[ i ].setPosition( position.x - 256, position.y - 128 + i * 32 ); texts[ i ] = new TextArea( "location/of/file" ); texts[ i ]->setCharacterSize( 20 ); texts[ i ]->setRectColor( sf::Color::Transparent ); texts[ i ]->setTextColor( textColor ); texts[ i ]->setPosition( sf::Vector2f( position.x - 256 + 32 + 4, position.y - 128 + i * 32 + 4 ) ); icons[ i ] = sf::Sprite(); } submitbar = sf::RectangleShape( sf::Vector2f( 512, 32 ) ); submitbar.setFillColor( sf::Color( 48, 48, 48 ) ); cam = new Camera(); sf::Vector2f pos; filename = new TextArea( "File name: " ); filename->setCharacterSize( 24 ); filename->setRectColor( sf::Color::Transparent ); filename->setTextColor( textColor ); pos.x = position.x - 256; pos.y = position.y + 256 - 128 - filename->getSize().y; filename->setPosition( pos ); selectedFilename = new TextArea( "" ); selectedFilename->setCharacterSize( 24 ); selectedFilename->setRectColor( sf::Color( 48, 48, 48 ) ); selectedFilename->setTextColor( textColor ); pos.x = position.x - 256 + filename->getSize().x; pos.y = position.y + 256 - 128 - selectedFilename->rect.getSize().y; selectedFilename->setPosition( pos ); selectedFilename->setRectSize( sf::Vector2f( 256 + 54, 30 ) ); submitButton = new TextButton( "submit" ); pos.x = position.x + 256 - submitButton->rect.getSize().x / 2; pos.y = position.y + 256 - 128 - 16; submitButton->setPosition( pos ); } void update( sf::Event & event, float dt ) { scrollbar->update( event ); if( event.type == sf::Event::MouseButtonPressed ) { if( event.mouseButton.button == sf::Mouse::Left ) { submitButton->click(); for( auto & txt: texts ) { if( txt->text.getGlobalBounds().contains( worldMousePosition ) ) { selectedFilename->setString( txt->s ); } } } } for( int i = 0; i < 7; i++ ) { texts[ i ]->setString( paths[ i + int( scrollbar->scrollValue ) ].path().string() ); icons[ i ] = sf::Sprite(); string extension = paths[ i + int( scrollbar->scrollValue ) ].path().extension().string(); if( extension == "" ) icons[ i ].setTexture( * getTexture( "GUI/icons/dictionary" )->texture ); else icons[ i ].setTexture( * getTexture( "GUI/icons/file" )->texture ); icons[ i ].setPosition( position.x - 256, position.y - 128 + i * 32 ); } submitButton->update( dt ); } void draw() { window->draw( rect ); window->draw( titlebar ); title->draw(); window->draw( submitbar ); filename->draw(); selectedFilename->draw(); submitButton->draw(); scrollbar->draw(); for( int i = 0; i < 7; i++ ) { window->draw( textField[ i ] ); texts[ i ]->draw(); window->draw( icons[ i ] ); } } };
#endif
użycie Open Dialog Box'asf::Clock timeClock; sf::Time prevTime; sf::Time currentTime; float dt;
sf::Vector2i mousePosition; sf::Vector2f worldMousePosition;
bool GUIwasHover; bool GUIwasClicked;
void testOpenDialogBox() { OpenDialogBox * openDial = new OpenDialogBox(); while( window->isOpen() ) { prevTime = currentTime; currentTime = timeClock.getElapsedTime(); dt = currentTime.asSeconds() - prevTime.asSeconds(); mousePosition = sf::Mouse::getPosition( * window ); worldMousePosition = window->mapPixelToCoords( mousePosition ); GUIwasHover = false; GUIwasClicked = false; sf::Event event; while( window->pollEvent( event ) ) { openDial->update( event, dt ); } window->clear(); openDial->draw(); window->display(); } }
|
|
madpl1239 |
» 2024-10-02 19:52:50 Ładnie napisany kod. Trzeba cię pochwalić. Dzisiaj wszedłem na forum i akurat na twój post. Na początku wydawało się mi, że "wyważasz otwarte drzwi", przecież jest sporo bibliotek opartych o SFML i nie tylko do "okraszania" aplikacji ładnymi GUI . Ja ostatnio ściągnąłem z git-a: tgui, imgui. Można powiedzieć, że te biblioteki wystarczają do różnych aplikacji: i tych "amatorskich" i tych bardziej profesjonalnych (takich, co to - no wiecie: co coś liczą i wypluwają wyniki w osobnych okienkach, a w innych okienkach mamy opcje do zmiany parametrów). Ale czytając dalej i przeglądając kod zacząłem czerpać przyjemność i tak sobie pomyślałem, przecież to jest fajne zadanie programistyczne napisać taki dialogbox od początku do końca. Zastanawiam się czy i ja nie popełnie takiego zadania w ramach ćwiczenia:)) Bo różnych swoich mniejszych, większych aplikacji mam mnóstwo, ale jakoś GUI u mnie zawsze leżało:)) Stąd widząc twoją robotę i zacięcie dostałem tzw. "powera" do zrobienia swojego małego GUI.
Może ten post za bardzo merytoryczny nie jest, ale chciałem tylko powiedzieć, że czasem oglądanie czyjejś pracy daje kopa, ażeby samemu spróbować. Więc dzięki wielkie za ten temat i trzymać tak dalej! Programowanie to sztuka sama w sobie - nie ma w niej mistrzów, są tylko mniej i bardziej doświadczeni:)))
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-02 23:01:05 Dzięki za docenienie mojej pracy. Ale jeszcze trzeba parę rzeczy dopisać i poprawić np. przemieszczanie się między katalogami, dodać grafikę do scrollbara, poprawić proporcje, skrócić ścieżki do plików. Jak to zrobię to wrzucę kod, bo pewnie się komuś przyda :-) Jeszcze mam pytanie, czy to dobra metoda na pobranie zaznaczonego pliku ? openDial->update( event, dt ); if( openDial->fileSelected == true ) { openDial->getFilename(); openDial = nullptr; }
|
|
madpl1239 |
» 2024-10-03 10:24:29 Ja tu błędu nie widzę, jeżeli chodzi o ten króciutki kod. Wydaje się poprawne logicznie - zakładając, że openDial->fileSelected działa poprawnie.
Tylko dlaczego openDial jet na końcu nullptr? Jakie to ma znaczenie? Czyżby po wyborze openDial kończył działalność. A co z jego destruktorem? Gdzie on jest? Przecież można by trochę posprzątać i wyzerować wewnętrzne zmienne obiektu openDial. Domyślny destruktor tego nie robi.
Gdy do openDial przypiszesz nullptr, to nie będzie wycieku pamięci? Skoro użyłeś w funkcji main() 'new' do zaalokowania openDial na stercie, to musisz pamiętać, żeby użyć delete do zwolnienia tej RAM. A delete potrzebuje tego wskaźnika jak wody:))
Więc openDial = nullptr to nie jest dobry pomysł. No chyba, że użyjesz inteligentnych wskaźników, które same dbają o to żeby usuwać instancje obiektów, na które wskazują. Tak działa C++
Ale szacun za piękny styl programowania.
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-03 17:27:43 Ok. Wrzuciłem tam delete. Nie do końca wiedziałem jak poprawnie usuwać obiekty. Teraz już wiem, dzięki :-) void testOpenDialogBox() { cam = new Camera(); OpenDialogBox * openDial = new OpenDialogBox(); while( window->isOpen() ) { prevTime = currentTime; currentTime = timeClock.getElapsedTime(); dt = currentTime.asSeconds() - prevTime.asSeconds(); mousePosition = sf::Mouse::getPosition( * window ); worldMousePosition = window->mapPixelToCoords( mousePosition ); GUIwasHover = false; GUIwasClicked = false; sf::Event event; while( window->pollEvent( event ) ) { if( openDial ) { openDial->update( event, dt ); if( openDial->fileSelected ) { cout << openDial->getFilename() << "\n"; delete openDial; openDial = nullptr; } } } window->clear(); if( openDial ) openDial->draw(); window->display(); } } |
|
1 2 « 3 » 4 5 |