JavaFX JavaFX - Spalten auf ganze SpreadsheetView verteilen

Bitte aktiviere JavaScript!
Guten Abend allerseits

Ich hab anfang des Jahres bereits viel mit der SpreadsheetView herumhantiert, bin mir aber nicht sicher ob ich das Problem damals gelöst hab. Wenn, dann finde ich die Lösung jedenfalls nicht mehr. :(

Folgendes: Ich möchte Zellen in einer SpreadsheetView anzeigen und diese mindestens auf die gesamte Breite der Tabelle aufblasen. Wenn es zuviele Zellen werden kann die Tabelle sich gerne mit Scrollbalken strecken, ich will aber in jedem Fall die Tabelle in der Breite nicht mehr nackig sehen. In der Höhe ist das so gewünscht wie es ist.

Ich hab mir gerade mal ein Update von ControlsFX gezogen, aber dort hab ich zwar eine Methode resizeRowsToMaximum() gefunden, die scheint genau das zu machen was ich will - jedoch nur für die Zeilenhöhe. Nicht für die Spaltenbreite, da gibt es nichts Vergleichbares. Und duckduckgo.com schmeißt mir für "controllsfx adjust cells to spreadsheetview" auch nichts Brauchbares raus.

Hat jemand eine Idee?
 
Oh man, und ich seh den Wald vor lauter Bäumen nicht...

fitColumns macht die Sache zwar besser, aber noch nicht so gut wie ich sie gerne hätte. Ich überleg schon, wieder auf TableView umzustellen.

Irgendwie bin ich mit den Tabellen von JavaFX einfach nicht zufrieden, die sind alle irgendwo Mist. Alles andere gefällt mir soweit und sieht klasse aus, aber Tabellendarstellungen sind allesamt irgendwo unvollständig. Liegt das daran daß ich Java 8 benutze und das dort nicht mehr so gepflegt wird? Oder tut sich da allgemein nicht mehr viel?
 
Mal eine Frage...wie groß würdet ihr den Aufwand schätzen, der SpreadsheetView in ControlsFX einige Extrafunktionen zu implementieren?
Konkret fehlen mir folgende Funktionen:
  • fitColumns()
  • Geschachtelte Spaltenheader
Ich meine, nur schimpfen und nix besser machen macht die Welt insgesamt nicht besser. Und auf ein halbgares Ergebnis hab ich auch keine Lust, das soll schon gut werden. Deshalb denk ich darüber nach, da selber etwas zu implementieren. (Und vielleicht hilft es anderen ja auch noch.)

Ich hab an GUI-Elementen noch nie rumgefummelt und keine Ahnung, wie das aufwändig das wird. Andererseits sind bei ControlsFX noch allerhand Issues offen, und viel scheint sich im letzten Jahr nicht mehr getan zu haben.

Edit:
Ich hab grad mal nachgesehen: Allein das Paket spreadsheet hat 4645 LoC (und damit ziemlich genau 1000 LoC mehr als mein ganzes Projekt). :eek:
 
Zuletzt bearbeitet:
Jup, das war der Fall... :)

Ich kenne SpreadsheetView leider nicht so genau, da ich es noch nicht brauchte. Aber ja: Tabellen sind etwas recht spezielles in JavaFX. Ich kann sie "hübsch" machen, aber bestimmte Dinge konnte ich auf Java8 damals nur mit Hacks machen.

Zu "javafx tableview fill width" konnte ich nur folgendes finden
Was das Spreadsheet angeht: Die Methode scheint nur dafür zu sorgen, dass aller Content *innerhalb* der Zelle (Sub-Zellen etc. inklusive) sichtbar ist. Ich würde mal mit prefWidth und maxWidth herum spielen. Vielleicht ist einiges vom TableView hier auch anwendbar (aus den Links oben).
Ansonsten: Ich bräuchte ein Lauffähiges Beispiel, mit dem ich das nachstellen könnte... Kannst du dazu einen Gist auf GitHub machen, oder so?
 
Ich kann sie "hübsch" machen, aber bestimmte Dinge konnte ich auf Java8 damals nur mit Hacks machen.
Würde es sich lohnen, auf Java 12 umzusatteln? Bisher hatte ich lediglich nur keinen Grund gehabt, aber das wäre mir Grund genug.

Lauffähiges Beispiel...hm...ich werd mal sehen was ich da machen kann. Vielleicht heute abend.
 
Pfff...und ich hab mir von einem Arbeitskollegen gerade einen Rant über Java anhören müssen. Er hat sich hauptsächlich an Swing ganz furchtbar gestört (was ich in der Form aber auch zum ersten Mal gehört habe)... :D
 
Er hat sich hauptsächlich an Swing ganz furchtbar gestört (was ich in der Form aber auch zum ersten Mal gehört habe)...
Schönen Gruß: das sind die, die es nicht können :p
Ok, Spaß bei Seite: Swing ist nicht einfach zu verwenden und wurde leider nicht weiter entwickelt. Was Swing gebraucht hätte, ist - neben einem Technologie-Upgrade - ein paar Vereinfachungen (vordefinierte Modelle), dann wäre das super geworden. Da könnte man mal James Gosling zitieren:
James Gosling hat gesagt.:
Swing ... is the most fully featured, flexible, whatever-way-you-want-to-measure-it UI tool kit on the planet. You can do the most amazing things with Swing. It's sort of the 747 cockpit of UI design tool kits, and flying a 747 is a little intimidating, and what people really want is a Cessna.
Bei FX habe ich den Eindruck, dass der Name Programm ist: Effekte. Das wundert mich auch nicht wirklich, denn zu der Zeit als FX aufkam, war Romain Guy recht aktiv, um genau das zu propagieren (Chet Haase und er haben "zufälligerweise" ein Buch darüber geschrieben, http://filthyrichclients.org/, Romain Guy hat seinerzeit gezeigt, dass man mit Swing auch schöne Oberflächen schreiben kann, z. B. Aerith)
 
Würde es sich lohnen, auf Java 12 umzusatteln? Bisher hatte ich lediglich nur keinen Grund gehabt, aber das wäre mir Grund genug.
Ja!
Nicht nur, weil Java selbst dann aktueller ist, sondern auch, wenn du mal so was ganz verrücktes wie einen WebView verwenden willst. Der auch noch performant ist.
Es gibt, ausser "Legacy"-Programme, für die man noch kein Budget für den Umzug nach Java(FX) 11+ bekommen hat (ja, sowas haben wir leider auch im Haus), keinen Grund, nicht Java(FX) 11+ zu verwenden. Auch in Bezug auf bessere HiDPI-Unterstützung etc. (@mihe7 übrigens soweit ich weiss, auch für Swing.)

In JavaFX ist irgendwie alles etwas recht speziell :p
@White_Fox hör nicht auf ihn. :)

JavaFX lässt sich IMHO extrem gut stylen (z.B auch, wenn ein Designer vorgaben macht), ist einfach um eigene Style-Klassen und Pseudoklassen zu erweitern, bietet ein solides Framework für Transitionen (die meisten Basis-Features genügen schon, aber es ist easy, neue & eigene Effekte zu erstellen) und hat einen guten Unterbau. Aber wie auch bei Swing ist man mitunter halt leider auf 3rd-Party-Produkte bei Widgets und so angewiesen.

Mal ein Beispiel von JavaFX, das echt gut aussieht: Und ja, auch Swing kann gut aussehen, wie IntelliJ beweist.
 
So, hier ist erstmal der Quellcode der Klassen.

Hier das besagte SpreadsheetView, es ist mittlerweile ebenfalls eine eigene Klasse geworden, der Quellcode ufert sonst fürchterlich aus und meiner Ansicht nach sollte eine Klasse möglichst nicht wesentlich größer als 500 Zeilen lang sein.

SpreadsheetView:
Java:
public class CenterviewStamptable extends SpreadsheetView implements ModelObservable{
    private View view;
    private MultiLangSupport lang;
    private ViewSettings settings;
    private StamppageModel activeStamppage;
    private ModelsViewLinkable model;
  
    private Grid centerviewStampgrid;

    public CenterviewStamptable(View view, ModelsViewLinkable model) {
        this.view = view;
        this.model = model;
        lang = new MultiLangSupport();
        settings = ViewSettings.getInstance();
        model.addModelobserver(this, ModelChange.THE_STAMPPAGE_AT_ACTIVE_PAGE_HAS_CHANGED);
        activeStamppage = model.getStamppageModel(model.getAddressOfActiveLibrarypage());
        init();
    }
  
    private void init(){
        setShowColumnHeader(true);
        setShowRowHeader(false);
        refreshActiveLibStampPage();
    }
  
    private void refreshActiveLibStampPage() {
        ObservableList<ObservableList<SpreadsheetCell>> rows;
        ObservableList<SpreadsheetCell> row;
        int rowcnt;
        int spanwidht;
        int spanstart;
      
        activeStamppage = model.getStamppageModel(model.getAddressOfActiveLibrarypage());
        centerviewStampgrid = new GridBase(0, 0);
      
        buildCenterviewStamptableheader();
      
        rows = FXCollections.observableArrayList();
        //Fill rows with data
        rowcnt = 0;
        for(StampsetModel stampset : activeStamppage.getRowModels()){
            row = getRowWithStampSetName(stampset.getName(), rowcnt++);
            rows.add(row);
          
            row = getRowWithStampDescriptions(stampset.getItemmodels(), rowcnt++);
            rows.add(row);
        }
        centerviewStampgrid.setRows(rows);
        //span name cells
        spanwidht = activeStamppage.cntPersistantProperties();
        spanstart = activeStamppage.cntTemporaryProperties();
        for (int spanrow = 0; spanrow < rowcnt; spanrow += 2) {
            centerviewStampgrid.spanColumn(spanwidht, spanrow, spanstart);
        }
        //Fit Columns
        for(SpreadsheetColumn column : this.getColumns()){
            column.fitColumn();
        }
        this.setGrid(centerviewStampgrid);
    }

    private void buildCenterviewStamptableheader() {
        if(activeStamppage.hasNoProperties()){
            centerviewStampgrid.getColumnHeaders().add(lang.getString(3080));
        }
        else{
            for (StamppageheaderModel stamppageHeader : activeStamppage.getColumnheaderModels()) {
                centerviewStampgrid.getColumnHeaders().add(stamppageHeader.propertyName);
            }
        }
    }
  
    private ObservableList<SpreadsheetCell> getRowWithStampSetName(String name, int rowcnt) {
        ObservableList<SpreadsheetCell> row;
        SpreadsheetCell cell;
        int columncnt;
      
        row = FXCollections.observableArrayList();
        if(activeStamppage.hasNoProperties()){
            cell = SpreadsheetCellType.STRING.createCell(rowcnt, 0, 1, 1, name);
            row.add(cell);
        }
        else{
            columncnt = 0;
            for(String s : activeStamppage.getTemporaryProperties()){
                cell = SpreadsheetCellType.STRING.createCell(rowcnt, columncnt, 1, 1, "");
                row.add(cell);
                columncnt++;
            }
            for(String s : activeStamppage.getPersistantProperties()){
                cell = SpreadsheetCellType.STRING.createCell(rowcnt, columncnt, 1, 1, name);
                row.add(cell);
                columncnt++;
            }
        }
        return row;
    }
    //TODO: Stampbeschreibung korrigieren, das stimmt hinten und vorne nicht.
    private ObservableList<SpreadsheetCell> getRowWithStampDescriptions(ArrayList<ComponentstampModel> itemmodels, int rowcnt) {
        ObservableList<SpreadsheetCell> row;
        SpreadsheetCell cell;
        int columnindex;
        String cellcontent;
      
        row = FXCollections.observableArrayList();
      
        if(activeStamppage.hasNoProperties()){
            cell = SpreadsheetCellType.STRING.createCell(rowcnt, 0, 1, 1, lang.getString(3081));
            row.add(cell);
        }
        else{
            columnindex = 0;
            for(ComponentstampModel component : itemmodels){
                cellcontent = component.getDescription();
                cell = SpreadsheetCellType.STRING.createCell(rowcnt, columnindex, 1, 1, cellcontent);
                row.add(cell);
                columnindex++;
            }
        }
        return row;
    }
  
    @Override
    public void notifyAboutChanges(ModelChange change) {
        if(change == ModelChange.THE_STAMPPAGE_AT_ACTIVE_PAGE_HAS_CHANGED){
            activeStamppage = model.getStamppageModel(model.getAddressOfActiveLibrarypage());
            refreshActiveLibStampPage();
        }
    }
}

View:
Java:
public class View implements ModelObservable{
  
    private ViewSettings settings;
    private MultiLangSupport lang;
    private SoftwareSettings swSettings = new SoftwareSettings();
    private CommandFactory commands;

    private ModelsViewLinkable model;
    private ControllersViewLinkable controller;

    private Stage mainStage;
    private BorderPane rootPane;
    private BorderPane mainPane;
    private SpreadsheetView centerviewStamptable;
    private StackPane centerviewStamppane;
    private StamptableContextmenu stampContextmenu;
    private SpreadsheetView centerviewComponenttable;
    private StackPane centerviewComponentpane;
    private Grid centerviewComponentgrid;
    private StamppageModel activeStamppage;
    private ComponentpageModel activeComponentpage;

    public View(ModelsViewLinkable model,
            ControllersViewLinkable controller) throws Exception {
      
        //Configurate settings
        settings = ViewSettings.getInstance();
        lang = new MultiLangSupport(swSettings.getPathForLanguagefiles(), settings.getStandardLanguage());

        this.controller = controller;
        this.model = model;
        this.commands = CommandFactory.newFactory();
      
        //Register as ModelObserver
        model.addModelobserver(this);
    }
  
    public void initGUI(Stage mainstage) throws IOException {
        this.mainStage = mainstage;

        //Generate main window
        rootPane = new BorderPane();
        Scene mainScene = new Scene(rootPane, 1000, 600);
        mainPane = new BorderPane();
        rootPane.setCenter(mainPane);

        initMenubar();
        initActivePagePane();

        refreshActiveLibComponentPage();

        this.mainStage.setScene(mainScene);
        this.mainStage.setTitle(lang.getString(1));
        this.mainStage.show();
    }
  
    private void initMenubar() throws IOException {
        //Create menubar
        MenuBar menubar = new MenuBar();
        menubar.prefWidthProperty().bind(mainStage.widthProperty());
        rootPane.setTop(menubar);
        //Filemenu
        Menu fileMenu = new Menu(lang.getString(100));
        menubar.getMenus().add(fileMenu);

        //Filemenu items
        Menu fileExport = new Menu(lang.getString(101));
        fileMenu.getItems().add(fileExport);
        MenuItem fileExit = new MenuItem(lang.getString(102));
        fileMenu.getItems().add(fileExit);

        //FileExport items
        MenuItem fileexportCSV = new MenuItem(lang.getString(103));
        fileExport.getItems().add(fileexportCSV);

        //Settingsmenu
        Menu settingsMenu = new Menu(lang.getString(300));
        menubar.getMenus().add(settingsMenu);

        //Settingsmenu items
        Menu settingsLanguage = new Menu(lang.getString(301));
        settingsMenu.getItems().add(settingsLanguage);
        for (Lang l : lang.getAvailableLangs()) {
            MenuItem lng = new MenuItem(l.getLangname());
            settingsLanguage.getItems().add(lng);
        }

        //Helpmenu
        Menu helpMenu = new Menu(lang.getString(500));
        menubar.getMenus().add(helpMenu);

        //Helpmenu items
        Menu helpTutorials = new Menu(lang.getString(501));
        helpMenu.getItems().add(helpTutorials);
    }
  
    private void initActivePagePane() {
        SplitPane centerPane = new SplitPane();
        mainPane.setCenter(centerPane);

        ScrollPane libraryBrowsePane = new ScrollPane();
        libraryBrowsePane.setMinSize(0, 0);
        libraryBrowsePane.setMaxSize(0, 0); //Todo: Remove this for V2 with library browser
        centerPane.getItems().add(libraryBrowsePane);

        //Make active libary page view
        TabPane activeLibraryPageView = new TabPane();
        centerPane.getItems().add(activeLibraryPageView);

        //Create tabs in library item view
        Tab libraryStampTab = new Tab(lang.getString(2000));
        libraryStampTab.setClosable(false);
        Tab libraryComponentTab = new Tab(lang.getString(2001));
        libraryComponentTab.setClosable(false);
        activeLibraryPageView.getTabs().addAll(libraryStampTab, libraryComponentTab);

        //Fill library stamp tab
        centerviewStamptable = new CenterviewStamptable(this, model);
        stampContextmenu = new StamptableContextmenu(this, model);
        centerviewStamptable.setContextMenu(stampContextmenu);
        centerviewStamptable.setOnContextMenuRequested(stampContextmenu);
        centerviewStamppane = new StackPane(centerviewStamptable);
        libraryStampTab.setContent(centerviewStamppane);

        //Fill library component tab
        centerviewComponentgrid = new GridBase(0, 0);
        centerviewComponenttable = new SpreadsheetView();
        centerviewComponenttable.setShowColumnHeader(true);
        centerviewComponenttable.setShowRowHeader(true);
        centerviewComponenttable.setContextMenu(new ComponenttableContextmenu());
        centerviewComponentpane = new StackPane(centerviewComponenttable);
        libraryComponentTab.setContent(centerviewComponentpane);

    }

    private void refreshActiveLibComponentPage() {
        ObservableList<ObservableList<SpreadsheetCell>> rows;
        ObservableList<SpreadsheetCell> row;
        int linecnt;
      
        activeComponentpage = model.getComponentpageModel(model.getAddressOfActiveLibrarypage());
        centerviewComponentgrid = new GridBase(0, 0);
        rows = FXCollections.observableArrayList();

        buildCenterviewComponenttableheader();
      
        //Fill rows with data
        rows = FXCollections.observableArrayList();
        linecnt = 0;
        while(linecnt < activeComponentpage.cntComponents()){
            row = getRowWithComponentdata(activeComponentpage.getComponentValues(linecnt), linecnt);
            rows.add(row);
            linecnt++;
        }
        centerviewComponentgrid.setRows(rows);
        centerviewComponenttable.setGrid(centerviewComponentgrid);
    }

    private void buildCenterviewComponenttableheader() {
        for(String s : activeComponentpage.getPropertyNames()){
            centerviewComponentgrid.getColumnHeaders().add(s);
        }
    }

    private ObservableList<SpreadsheetCell> getRowWithComponentdata(ArrayList<String> componentValues, int linecnt) {
        SpreadsheetCell cell;
        ObservableList<SpreadsheetCell> row;
        int columncnt;
      
        row = FXCollections.observableArrayList();
        columncnt = 0;
      
        for(String s : activeComponentpage.getComponentValues(linecnt)){
            cell = SpreadsheetCellType.STRING.createCell(linecnt, columncnt, 1, 1, s);
            row.add(cell);
            columncnt++;
        }
        return row;
    }
  
    @Override
    public void notifyAboutChanges(ModelChange change) {
        switch (change){
            case THE_COMPONENTPAGE_AT_ACTIVE_PAGE_HAS_CHANGED:
                refreshActiveLibComponentPage();
                break;
            case THE_STAMPPAGE_AT_ACTIVE_PAGE_HAS_CHANGED:
                break;
            default:
                throw new UnsupportedOperationException("View gets unsupported ModelChange enumeration.");
        }
    }
  
    SpreadsheetViewSelectionModel getStamppageSelectionmodel(){
        return centerviewStamptable.getSelectionModel();
    }
  
    /**
     * Add a new StampSet to the active StampPage.
     */
    void addNewStampsetToActiveStamppage(){
        String s;
        StampSet set;
        Optional<String> result;
      
        TextInputDialog d = new TextInputDialog();
        d.setTitle(lang.getString(3000));
        d.setHeaderText(lang.getString(3001));
        d.setContentText(lang.getString(3002));
        result = d.showAndWait();
        if(!result.isPresent()){return;}
        s = d.getResult();
      
        set = new StampSet(s);
        AddNewStampsetToStamppageCommand  command = commands.newAddNewStampsetToStamppageCommand(
                set, model.getAddressOfActiveLibrarypage());
        controller.requestCommand(command);
    }
  
    /**
     * Add a new property to the active StampPage.
     */
    void addNewPropertyToActiveStamppage() {
        KindOfProperty k;
        String s;
        Optional<String> tdResult;
        Optional<String> cdResult;
      
        TextInputDialog td = new TextInputDialog();
        td.setTitle(lang.getString(3100));
        td.setHeaderText(lang.getString(3101));
        td.setContentText(lang.getString(3102));
        tdResult = td.showAndWait();
        if(!tdResult.isPresent()){return;}
        s = td.getResult();
      
        ChoiceDialog<String> cd = new ChoiceDialog<>(
                lang.getString(3103), lang.getString(3103), lang.getString(3104));
        cd.setTitle(lang.getString(3105));
        cd.setHeaderText(lang.getString(3106));
        cd.setContentText(lang.getString(3107));
        cdResult = cd.showAndWait();
        if(!cdResult.isPresent()){return;}
        if(cd.getResult().equals(lang.getString(3103))){
            k = KindOfProperty.PERSISTANT;
        }
        else{
            k = KindOfProperty.TEMPORARY;
        }
      
        AddNewPropertyToStamppageCommand command = commands.newAddNewPropertyToStamppageCommand(
                model.getAddressOfActiveLibrarypage(), k, s);
        controller.requestCommand(command);
    }
  
    void addComponentstampToActiveStamptable(StampClass stamp){
    }
  
    void removeComponentstampFromActiveStamppage(){
    }
  
    void removePropertyColumnFromActiveStamppage(){
    }
  
    void renameStampsetAtActiveStamppage(){
    }
  
    void removeStampsetRowFromActiveStamppage(){
    }
  
    void generateData(){
    }

    void renamePropertyColumnAtActiveStamppage() {
    }

    void modifyComponentStampAtActiveStamppage() {
    }
}


Nachtrag:
Ich trenne mich nur so ungern von Netbeans 8... :(
Aber mal schauen.
 
Ich trenne mich nur so ungern von Netbeans 8... :(
https://netbeans.apache.org/download/index.html - NetBeans 11 ist aber aktuell! :eek:

Zum Code: Was sind die Dependencies (Maven oder Gradle)? Speziell Klassen wie ModelObservable oder ModelsViewLinkable, ControllersViewLinkable (verwende vielleicht aus Faulheit eigentlich nie MVVN, sondern meist nur MVC - wenn das also von einer Dependency stammt, brauch ich die natürlich auch).
Du hast sicher recht, dass es sonst ausufert, aber das Beispiel sollte natürlich selbständig ausführbar sein, damit ich damit herumspielen kann.
 
Oh weh, da rächt sich gleich einiges, daß ich bisher auf die lange Bank geschoben hab, auf einmal. :(
NetBeans 11 ist aber aktuell!
Ich weiß. Irgendein neueres Netbeans (Ich hab grad nachgesehen, es war V10) hab ich sogar schon, mich haben jedoch allerhand Dinge daran bisher gestört. Als ich Netbeans das letzte Mal angetestet habe, hat die Plug-In-Unterstützung die Netbeansplugins noch nicht drin gehabt (ich meine die Online-Quellen). Und da ich jede Menge Plugins in Netbeans drin habe war der einzige Weg, Apache Netbeans so hinzubiegen wie ich es gewohnt war, Netbeans neu zu installieren und bei der Installation die Einstellungen aus Netbeans 8 zu importieren.
Und auch wenn ich des Englischen bestimmt mächtig genug bin, ist mir ein Programm das in meiner Muttersprache kommuniziert, deutlich lieber und so schnell wie Netbeans 9, 10 und 11 kamen (und wie lange die Übersetzung früher immer gedauert hat) bin ich mir nicht sicher, ob es von Netbeans >8 je eine andere Sprachversion jenseits von Englisch und Chinesisch geben wird.

Ansonsten werd ich mal sehen, daß ich das mit Maven oder Gradle zusammenstöpsele.

Google würde dazu sicherlich jede Menge Ergebnisse ausspucken, trotzdem würde mich mal eure Meinung interessieren: Was ist der Unterschied zwischen Maven und Gradle, welches ist leichter zu bedienen (bei Maven muß man dauernd in einer xml-Datei rumfummeln soweit ich weiß, deswegen hab ich mich da bisher herumgemogelt), und was findet ihr persönlich besser?
 
Was die englische Sprachversion angeht: Da kommst du nicht drumherum. Längerfristig ist es eh besser, die englische zu nehmen, da die meiste Hilfe (wenn du mal was bzgl. NetBeans brauchst) eh auf Englisch ist und die englische Version der IDE adressiert.
Klemm dich da lieber eher früher als später hinter.

Maven v.s. Gradle ist schwer zu beantworten. Ich favorisiere Maven, allerdings gehen manche speziellen Sachen, wenn du z.B. spezielle eigene Tasks benötigst, die nicht bereits von einem Plugin abgedeckt sind, mit Gradle sicher leichter. Es ist ein wenig Geschmackssache ob du deinen Build lieber deklarativ oder imperativ gestaltest. Und XML magst, oder nicht. :D:p
Und auch hier empfiehlt es sich wieder, Englisch zu können, wenn du Hilfe brauchst...
 
Es ist kein Problem (die meisten Programme, mit denen ich arbeite, gibt es ausschließlich mit englischsprachigem UI, z.B. Embedded Studio, ST Cube MX oder vor allem Altium), eher eine Mischung aus Gewohnheit und Prinzip.

Ich hab gerade mal NB 11.1 installiert, bin damit aber gerade ziemlich frustriert. Aber das ist Gegenstand eines anderen Threads. ;)
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben